diff --git a/COPYRIGHT.OpenSource b/COPYRIGHT.OpenSource index 9dec1963e4d9861eab75571b72948edb67adf700..ffcf920154cbb18b27fe6ee4c83f09e89949efcd 100755 --- a/COPYRIGHT.OpenSource +++ b/COPYRIGHT.OpenSource @@ -8,7 +8,7 @@ THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL Copyright Notice and License Texts ---------------------------------------------------------------------- -Software: opencv v4.13.0 +Software: opencv v4.11.0 Copyright notice: Copyright (C) 2000-2022, Intel Corporation, all rights reserved. @@ -20,6 +20,7 @@ Copyright (C) 2008-2016, Itseez Inc., all rights reserved. Copyright (C) 2019-2023, Xperience AI, all rights reserved. Copyright (C) 2019-2022, Shenzhen Institute of Artificial Intelligence and Robotics for Society, all rights reserved. Copyright (C) 2022-2023, Southern University of Science And Technology, all rights reserved. +Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. License: Apache License 2.0 Apache License @@ -407,4 +408,33 @@ License: Apache License 2.0 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. +---------------------------------------------------------------------- + +Software: spdlog v1.15.3 + +Copyright notice: +Copyright Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +License: MIT License + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/LICENSE.OpenSource b/LICENSE.OpenSource index 6f2cce43137407752069c5ceaab75c78cd4581fe..0cfcc9f7fa192b3f26ca70692440c67aee954118 100755 --- a/LICENSE.OpenSource +++ b/LICENSE.OpenSource @@ -1,10 +1,14 @@ -The directories below are licensed under Apache License V2.0. +(1) The directories below are licensed under Apache License V2.0. ./vendor/opensource/opencv/clang ./vendor/opensource/opencv/gcc ./vendor/opensource/osd/clang ./vendor/opensource/osd/gcc +(2) The directories below are licensed under MIT License +./vendor/opensource/log_lib/spdlog + +(a) Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -206,3 +210,26 @@ The directories below are licensed under Apache License V2.0. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +(b) +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/opensource/log_lib/spdlog/async.h b/vendor/opensource/log_lib/spdlog/async.h new file mode 100755 index 0000000000000000000000000000000000000000..92fcd9a7da104e38d82987a6cc90d03019199e41 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/async.h @@ -0,0 +1,99 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Async logging using global thread pool +// All loggers created here share same global thread pool. +// Each log message is pushed to a queue along with a shared pointer to the +// logger. +// If a logger deleted while having pending messages in the queue, it's actual +// destruction will defer +// until all its messages are processed by the thread pool. +// This is because each message in the queue holds a shared_ptr to the +// originating logger. + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { + +namespace details { +static const size_t default_async_q_size = 8192; +} + +// async logger factory - creates async loggers backed with thread pool. +// if a global thread pool doesn't already exist, create it with default queue +// size of 8192 items and single thread. +template +struct async_factory_impl { + template + static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { + auto ®istry_inst = details::registry::instance(); + + // create global thread pool if not already exists.. + + auto &mutex = registry_inst.tp_mutex(); + std::lock_guard tp_lock(mutex); + auto tp = registry_inst.get_tp(); + if (tp == nullptr) { + tp = std::make_shared(details::default_async_q_size, 1U); + registry_inst.set_tp(tp); + } + + auto sink = std::make_shared(std::forward(args)...); + auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), + std::move(tp), OverflowPolicy); + registry_inst.initialize_logger(new_logger); + return new_logger; + } +}; + +using async_factory = async_factory_impl; +using async_factory_nonblock = async_factory_impl; + +template +inline std::shared_ptr create_async(std::string logger_name, + SinkArgs &&...sink_args) { + return async_factory::create(std::move(logger_name), + std::forward(sink_args)...); +} + +template +inline std::shared_ptr create_async_nb(std::string logger_name, + SinkArgs &&...sink_args) { + return async_factory_nonblock::create(std::move(logger_name), + std::forward(sink_args)...); +} + +// set global thread pool. +inline void init_thread_pool(size_t q_size, + size_t thread_count, + std::function on_thread_start, + std::function on_thread_stop) { + auto tp = std::make_shared(q_size, thread_count, on_thread_start, + on_thread_stop); + details::registry::instance().set_tp(std::move(tp)); +} + +inline void init_thread_pool(size_t q_size, + size_t thread_count, + std::function on_thread_start) { + init_thread_pool(q_size, thread_count, on_thread_start, [] {}); +} + +inline void init_thread_pool(size_t q_size, size_t thread_count) { + init_thread_pool(q_size, thread_count, [] {}, [] {}); +} + +// get the global thread pool. +inline std::shared_ptr thread_pool() { + return details::registry::instance().get_tp(); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/async_logger-inl.h b/vendor/opensource/log_lib/spdlog/async_logger-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..a681d97c6d44c2ee7f2cb4077ac7516e34279635 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/async_logger-inl.h @@ -0,0 +1,84 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name, + sinks_init_list sinks_list, + std::weak_ptr tp, + async_overflow_policy overflow_policy) + : async_logger(std::move(logger_name), + sinks_list.begin(), + sinks_list.end(), + std::move(tp), + overflow_policy) {} + +SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name, + sink_ptr single_sink, + std::weak_ptr tp, + async_overflow_policy overflow_policy) + : async_logger( + std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) {} + +// send the log message to the thread pool +SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg){ + SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){ + pool_ptr -> post_log(shared_from_this(), msg, overflow_policy_); +} +else { + throw_spdlog_ex("async log: thread pool doesn't exist anymore"); +} +} +SPDLOG_LOGGER_CATCH(msg.source) +} + +// send flush request to the thread pool +SPDLOG_INLINE void spdlog::async_logger::flush_(){ + SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){ + pool_ptr -> post_flush(shared_from_this(), overflow_policy_); +} +else { + throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); +} +} +SPDLOG_LOGGER_CATCH(source_loc()) +} + +// +// backend functions - called from the thread pool to do the actual job +// +SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) { + for (auto &sink : sinks_) { + if (sink->should_log(msg.level)) { + SPDLOG_TRY { sink->log(msg); } + SPDLOG_LOGGER_CATCH(msg.source) + } + } + + if (should_flush_(msg)) { + backend_flush_(); + } +} + +SPDLOG_INLINE void spdlog::async_logger::backend_flush_() { + for (auto &sink : sinks_) { + SPDLOG_TRY { sink->flush(); } + SPDLOG_LOGGER_CATCH(source_loc()) + } +} + +SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) { + auto cloned = std::make_shared(*this); + cloned->name_ = std::move(new_name); + return cloned; +} diff --git a/vendor/opensource/log_lib/spdlog/async_logger.h b/vendor/opensource/log_lib/spdlog/async_logger.h new file mode 100755 index 0000000000000000000000000000000000000000..846c4c6f080290f3022fecede2c85dfedaafa618 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/async_logger.h @@ -0,0 +1,74 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Fast asynchronous logger. +// Uses pre allocated queue. +// Creates a single back thread to pop messages from the queue and log them. +// +// Upon each log write the logger: +// 1. Checks if its log level is enough to log the message +// 2. Push a new copy of the message to a queue (or block the caller until +// space is available in the queue) +// Upon destruction, logs all remaining messages in the queue before +// destructing.. + +#include + +namespace spdlog { + +// Async overflow policy - block by default. +enum class async_overflow_policy { + block, // Block until message can be enqueued + overrun_oldest, // Discard oldest message in the queue if full when trying to + // add new item. + discard_new // Discard new message if the queue is full when trying to add new item. +}; + +namespace details { +class thread_pool; +} + +class SPDLOG_API async_logger final : public std::enable_shared_from_this, + public logger { + friend class details::thread_pool; + +public: + template + async_logger(std::string logger_name, + It begin, + It end, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block) + : logger(std::move(logger_name), begin, end), + thread_pool_(std::move(tp)), + overflow_policy_(overflow_policy) {} + + async_logger(std::string logger_name, + sinks_init_list sinks_list, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + async_logger(std::string logger_name, + sink_ptr single_sink, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + std::shared_ptr clone(std::string new_name) override; + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + void backend_sink_it_(const details::log_msg &incoming_log_msg); + void backend_flush_(); + +private: + std::weak_ptr thread_pool_; + async_overflow_policy overflow_policy_; +}; +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "async_logger-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/cfg/argv.h b/vendor/opensource/log_lib/spdlog/cfg/argv.h new file mode 100755 index 0000000000000000000000000000000000000000..7de2f83e7d2a5fa9dec8a90e8e0d4ec79c9620ed --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/cfg/argv.h @@ -0,0 +1,40 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +#include +#include + +// +// Init log levels using each argv entry that starts with "SPDLOG_LEVEL=" +// +// set all loggers to debug level: +// example.exe "SPDLOG_LEVEL=debug" + +// set logger1 to trace level +// example.exe "SPDLOG_LEVEL=logger1=trace" + +// turn off all logging except for logger1 and logger2: +// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info" + +namespace spdlog { +namespace cfg { + +// search for SPDLOG_LEVEL= in the args and use it to init the levels +inline void load_argv_levels(int argc, const char **argv) { + const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + if (arg.find(spdlog_level_prefix) == 0) { + auto levels_string = arg.substr(spdlog_level_prefix.size()); + helpers::load_levels(levels_string); + } + } +} + +inline void load_argv_levels(int argc, char **argv) { + load_argv_levels(argc, const_cast(argv)); +} + +} // namespace cfg +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/cfg/env.h b/vendor/opensource/log_lib/spdlog/cfg/env.h new file mode 100755 index 0000000000000000000000000000000000000000..47bf61c721e14a8141672661cf79ca460133837c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/cfg/env.h @@ -0,0 +1,36 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +#include +#include +#include + +// +// Init levels and patterns from env variables SPDLOG_LEVEL +// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). +// Note - fallback to "info" level on unrecognized levels +// +// Examples: +// +// set global level to debug: +// export SPDLOG_LEVEL=debug +// +// turn off all logging except for logger1: +// export SPDLOG_LEVEL="*=off,logger1=debug" +// + +// turn off all logging except for logger1 and logger2: +// export SPDLOG_LEVEL="off,logger1=debug,logger2=info" + +namespace spdlog { +namespace cfg { +inline void load_env_levels(const char* var = "SPDLOG_LEVEL") { + auto env_val = details::os::getenv(var); + if (!env_val.empty()) { + helpers::load_levels(env_val); + } +} + +} // namespace cfg +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/cfg/helpers-inl.h b/vendor/opensource/log_lib/spdlog/cfg/helpers-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..93650a2e843f2e118a9e458218f9ec1183c7e541 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/cfg/helpers-inl.h @@ -0,0 +1,107 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +namespace spdlog { +namespace cfg { +namespace helpers { + +// inplace convert to lowercase +inline std::string &to_lower_(std::string &str) { + std::transform(str.begin(), str.end(), str.begin(), [](char ch) { + return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); + }); + return str; +} + +// inplace trim spaces +inline std::string &trim_(std::string &str) { + const char *spaces = " \n\r\t"; + str.erase(str.find_last_not_of(spaces) + 1); + str.erase(0, str.find_first_not_of(spaces)); + return str; +} + +// return (name,value) trimmed pair from given "name=value" string. +// return empty string on missing parts +// "key=val" => ("key", "val") +// " key = val " => ("key", "val") +// "key=" => ("key", "") +// "val" => ("", "val") + +inline std::pair extract_kv_(char sep, const std::string &str) { + auto n = str.find(sep); + std::string k, v; + if (n == std::string::npos) { + v = str; + } else { + k = str.substr(0, n); + v = str.substr(n + 1); + } + return std::make_pair(trim_(k), trim_(v)); +} + +// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.." +// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...} +inline std::unordered_map extract_key_vals_(const std::string &str) { + std::string token; + std::istringstream token_stream(str); + std::unordered_map rv{}; + while (std::getline(token_stream, token, ',')) { + if (token.empty()) { + continue; + } + auto kv = extract_kv_('=', token); + rv[kv.first] = kv.second; + } + return rv; +} + +SPDLOG_INLINE void load_levels(const std::string &input) { + if (input.empty() || input.size() > 512) { + return; + } + + auto key_vals = extract_key_vals_(input); + std::unordered_map levels; + level::level_enum global_level = level::info; + bool global_level_found = false; + + for (auto &name_level : key_vals) { + auto &logger_name = name_level.first; + auto level_name = to_lower_(name_level.second); + auto level = level::from_str(level_name); + // ignore unrecognized level names + if (level == level::off && level_name != "off") { + continue; + } + if (logger_name.empty()) // no logger name indicate global level + { + global_level_found = true; + global_level = level; + } else { + levels[logger_name] = level; + } + } + + details::registry::instance().set_levels(std::move(levels), + global_level_found ? &global_level : nullptr); +} + +} // namespace helpers +} // namespace cfg +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/cfg/helpers.h b/vendor/opensource/log_lib/spdlog/cfg/helpers.h new file mode 100755 index 0000000000000000000000000000000000000000..c02381891c3dc3812701c2433ba35756bce968de --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/cfg/helpers.h @@ -0,0 +1,29 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace cfg { +namespace helpers { +// +// Init levels from given string +// +// Examples: +// +// set global level to debug: "debug" +// turn off all logging except for logger1: "off,logger1=debug" +// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" +// +SPDLOG_API void load_levels(const std::string &txt); +} // namespace helpers + +} // namespace cfg +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "helpers-inl.h" +#endif // SPDLOG_HEADER_ONLY diff --git a/vendor/opensource/log_lib/spdlog/common-inl.h b/vendor/opensource/log_lib/spdlog/common-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..a8a0453c14d72550d29f23122d01fd638e7828ac --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/common-inl.h @@ -0,0 +1,68 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace level { + +#if __cplusplus >= 201703L +constexpr +#endif + static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES; + +static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES; + +SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT { + return level_string_views[l]; +} + +SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT { + return short_level_names[l]; +} + +SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT { + auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name); + if (it != std::end(level_string_views)) + return static_cast(std::distance(std::begin(level_string_views), it)); + + // check also for "warn" and "err" before giving up.. + if (name == "warn") { + return level::warn; + } + if (name == "err") { + return level::err; + } + return level::off; +} +} // namespace level + +SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) + : msg_(std::move(msg)) {} + +SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) { +#ifdef SPDLOG_USE_STD_FORMAT + msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what(); +#else + memory_buf_t outbuf; + fmt::format_system_error(outbuf, last_errno, msg.c_str()); + msg_ = fmt::to_string(outbuf); +#endif +} + +SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT { return msg_.c_str(); } + +SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) { + SPDLOG_THROW(spdlog_ex(msg, last_errno)); +} + +SPDLOG_INLINE void throw_spdlog_ex(std::string msg) { SPDLOG_THROW(spdlog_ex(std::move(msg))); } + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/common.h b/vendor/opensource/log_lib/spdlog/common.h new file mode 100755 index 0000000000000000000000000000000000000000..580fbd7f7e66e21b4c607236c6db9d2765494ff7 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/common.h @@ -0,0 +1,406 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SPDLOG_USE_STD_FORMAT + #include + #if __cpp_lib_format >= 202207L + #include + #else + #include + #endif +#endif + +#ifdef SPDLOG_COMPILED_LIB + #undef SPDLOG_HEADER_ONLY + #if defined(SPDLOG_SHARED_LIB) + #if defined(_WIN32) + #ifdef spdlog_EXPORTS + #define SPDLOG_API __declspec(dllexport) + #else // !spdlog_EXPORTS + #define SPDLOG_API __declspec(dllimport) + #endif + #else // !defined(_WIN32) + #define SPDLOG_API __attribute__((visibility("default"))) + #endif + #else // !defined(SPDLOG_SHARED_LIB) + #define SPDLOG_API + #endif + #define SPDLOG_INLINE +#else // !defined(SPDLOG_COMPILED_LIB) + #define SPDLOG_API + #define SPDLOG_HEADER_ONLY + #define SPDLOG_INLINE inline +#endif // #ifdef SPDLOG_COMPILED_LIB + +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) && \ + FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8 + #define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) + #define SPDLOG_FMT_STRING(format_string) FMT_STRING(format_string) + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + #include + #endif +#else + #define SPDLOG_FMT_RUNTIME(format_string) format_string + #define SPDLOG_FMT_STRING(format_string) format_string +#endif + +// visual studio up to 2013 does not support noexcept nor constexpr +#if defined(_MSC_VER) && (_MSC_VER < 1900) + #define SPDLOG_NOEXCEPT _NOEXCEPT + #define SPDLOG_CONSTEXPR +#else + #define SPDLOG_NOEXCEPT noexcept + #define SPDLOG_CONSTEXPR constexpr +#endif + +// If building with std::format, can just use constexpr, otherwise if building with fmt +// SPDLOG_CONSTEXPR_FUNC needs to be set the same as FMT_CONSTEXPR to avoid situations where +// a constexpr function in spdlog could end up calling a non-constexpr function in fmt +// depending on the compiler +// If fmt determines it can't use constexpr, we should inline the function instead +#ifdef SPDLOG_USE_STD_FORMAT + #define SPDLOG_CONSTEXPR_FUNC constexpr +#else // Being built with fmt + #if FMT_USE_CONSTEXPR + #define SPDLOG_CONSTEXPR_FUNC FMT_CONSTEXPR + #else + #define SPDLOG_CONSTEXPR_FUNC inline + #endif +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define SPDLOG_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define SPDLOG_DEPRECATED __declspec(deprecated) +#else + #define SPDLOG_DEPRECATED +#endif + +// disable thread local on msvc 2013 +#ifndef SPDLOG_NO_TLS + #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt) + #define SPDLOG_NO_TLS 1 + #endif +#endif + +#ifndef SPDLOG_FUNCTION + #define SPDLOG_FUNCTION static_cast(__FUNCTION__) +#endif + +#ifdef SPDLOG_NO_EXCEPTIONS + #define SPDLOG_TRY + #define SPDLOG_THROW(ex) \ + do { \ + printf("spdlog fatal error: %s\n", ex.what()); \ + std::abort(); \ + } while (0) + #define SPDLOG_CATCH_STD +#else + #define SPDLOG_TRY try + #define SPDLOG_THROW(ex) throw(ex) + #define SPDLOG_CATCH_STD \ + catch (const std::exception &) { \ + } +#endif + +namespace spdlog { + +class formatter; + +namespace sinks { +class sink; +} + +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +using filename_t = std::wstring; + // allow macro expansion to occur in SPDLOG_FILENAME_T + #define SPDLOG_FILENAME_T_INNER(s) L##s + #define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s) +#else +using filename_t = std::string; + #define SPDLOG_FILENAME_T(s) s +#endif + +using log_clock = std::chrono::system_clock; +using sink_ptr = std::shared_ptr; +using sinks_init_list = std::initializer_list; +using err_handler = std::function; +#ifdef SPDLOG_USE_STD_FORMAT +namespace fmt_lib = std; + +using string_view_t = std::string_view; +using memory_buf_t = std::string; + +template + #if __cpp_lib_format >= 202207L +using format_string_t = std::format_string; + #else +using format_string_t = std::string_view; + #endif + +template +struct is_convertible_to_basic_format_string + : std::integral_constant>::value> {}; + + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = std::wstring_view; +using wmemory_buf_t = std::wstring; + +template + #if __cpp_lib_format >= 202207L +using wformat_string_t = std::wformat_string; + #else +using wformat_string_t = std::wstring_view; + #endif + #endif + #define SPDLOG_BUF_TO_STRING(x) x +#else // use fmt lib instead of std::format +namespace fmt_lib = fmt; + +using string_view_t = fmt::basic_string_view; +using memory_buf_t = fmt::basic_memory_buffer; + +template +using format_string_t = fmt::format_string; + +template +using remove_cvref_t = typename std::remove_cv::type>::type; + +template + #if FMT_VERSION >= 90101 +using fmt_runtime_string = fmt::runtime_format_string; + #else +using fmt_runtime_string = fmt::basic_runtime; + #endif + +// clang doesn't like SFINAE disabled export_class in std::is_convertible<> so have to repeat the +// condition from basic_format_string here, in addition, fmt::basic_runtime is only +// convertible to basic_format_string but not basic_string_view +template +struct is_convertible_to_basic_format_string + : std::integral_constant>::value || + std::is_same, fmt_runtime_string>::value> { +}; + + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = fmt::basic_string_view; +using wmemory_buf_t = fmt::basic_memory_buffer; + +template +using wformat_string_t = fmt::wformat_string; + #endif + #define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x) +#endif + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + #ifndef _WIN32 + #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows + #endif // _WIN32 +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + +template +struct is_convertible_to_any_format_string + : std::integral_constant::value || + is_convertible_to_basic_format_string::value> {}; + +#if defined(SPDLOG_NO_ATOMIC_LEVELS) +using level_t = details::null_atomic_int; +#else +using level_t = std::atomic; +#endif + +#define SPDLOG_LEVEL_TRACE 0 +#define SPDLOG_LEVEL_DEBUG 1 +#define SPDLOG_LEVEL_INFO 2 +#define SPDLOG_LEVEL_WARN 3 +#define SPDLOG_LEVEL_ERROR 4 +#define SPDLOG_LEVEL_CRITICAL 5 +#define SPDLOG_LEVEL_OFF 6 + +#if !defined(SPDLOG_ACTIVE_LEVEL) + #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +#endif + +// Log level enum +namespace level { +enum level_enum : int { + trace = SPDLOG_LEVEL_TRACE, + debug = SPDLOG_LEVEL_DEBUG, + info = SPDLOG_LEVEL_INFO, + warn = SPDLOG_LEVEL_WARN, + err = SPDLOG_LEVEL_ERROR, + critical = SPDLOG_LEVEL_CRITICAL, + off = SPDLOG_LEVEL_OFF, + n_levels +}; + +#define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t("trace", 5) +#define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t("debug", 5) +#define SPDLOG_LEVEL_NAME_INFO spdlog::string_view_t("info", 4) +#define SPDLOG_LEVEL_NAME_WARNING spdlog::string_view_t("warning", 7) +#define SPDLOG_LEVEL_NAME_ERROR spdlog::string_view_t("error", 5) +#define SPDLOG_LEVEL_NAME_CRITICAL spdlog::string_view_t("critical", 8) +#define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t("off", 3) + +#if !defined(SPDLOG_LEVEL_NAMES) + #define SPDLOG_LEVEL_NAMES \ + { \ + SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \ + SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \ + SPDLOG_LEVEL_NAME_OFF \ + } +#endif + +#if !defined(SPDLOG_SHORT_LEVEL_NAMES) + + #define SPDLOG_SHORT_LEVEL_NAMES \ + { "T", "D", "I", "W", "E", "C", "O" } +#endif + +SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; + +} // namespace level + +// +// Color mode used by sinks with color support. +// +enum class color_mode { always, automatic, never }; + +// +// Pattern time - specific time getting to use for pattern_formatter. +// local time by default +// +enum class pattern_time_type { + local, // log localtime + utc // log utc +}; + +// +// Log exception +// +class SPDLOG_API spdlog_ex : public std::exception { +public: + explicit spdlog_ex(std::string msg); + spdlog_ex(const std::string &msg, int last_errno); + const char *what() const SPDLOG_NOEXCEPT override; + +private: + std::string msg_; +}; + +[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno); +[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg); + +struct source_loc { + SPDLOG_CONSTEXPR source_loc() = default; + SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in) + : filename{filename_in}, + line{line_in}, + funcname{funcname_in} {} + + SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line <= 0; } + const char *filename{nullptr}; + int line{0}; + const char *funcname{nullptr}; +}; + +struct file_event_handlers { + file_event_handlers() + : before_open(nullptr), + after_open(nullptr), + before_close(nullptr), + after_close(nullptr) {} + + std::function before_open; + std::function after_open; + std::function before_close; + std::function after_close; +}; + +namespace details { + +// to_string_view + +SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf) + SPDLOG_NOEXCEPT { + return spdlog::string_view_t{buf.data(), buf.size()}; +} + +SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str) + SPDLOG_NOEXCEPT { + return str; +} + +#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf) + SPDLOG_NOEXCEPT { + return spdlog::wstring_view_t{buf.data(), buf.size()}; +} + +SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str) + SPDLOG_NOEXCEPT { + return str; +} +#endif + +#if defined(SPDLOG_USE_STD_FORMAT) && __cpp_lib_format >= 202207L +template +SPDLOG_CONSTEXPR_FUNC std::basic_string_view to_string_view( + std::basic_format_string fmt) SPDLOG_NOEXCEPT { + return fmt.get(); +} +#endif + +// make_unique support for pre c++14 +#if __cplusplus >= 201402L // C++14 and beyond +using std::enable_if_t; +using std::make_unique; +#else +template +using enable_if_t = typename std::enable_if::type; + +template +std::unique_ptr make_unique(Args &&...args) { + static_assert(!std::is_array::value, "arrays not supported"); + return std::unique_ptr(new T(std::forward(args)...)); +} +#endif + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template ::value, int> = 0> +constexpr T conditional_static_cast(U value) { + return static_cast(value); +} + +template ::value, int> = 0> +constexpr T conditional_static_cast(U value) { + return value; +} + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "common-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/backtracer-inl.h b/vendor/opensource/log_lib/spdlog/details/backtracer-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..43d1002478c8407e3d1ba2bf18fadf76a9241b5e --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/backtracer-inl.h @@ -0,0 +1,63 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif +namespace spdlog { +namespace details { +SPDLOG_INLINE backtracer::backtracer(const backtracer &other) { + std::lock_guard lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = other.messages_; +} + +SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT { + std::lock_guard lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); +} + +SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) { + std::lock_guard lock(mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); + return *this; +} + +SPDLOG_INLINE void backtracer::enable(size_t size) { + std::lock_guard lock{mutex_}; + enabled_.store(true, std::memory_order_relaxed); + messages_ = circular_q{size}; +} + +SPDLOG_INLINE void backtracer::disable() { + std::lock_guard lock{mutex_}; + enabled_.store(false, std::memory_order_relaxed); +} + +SPDLOG_INLINE bool backtracer::enabled() const { return enabled_.load(std::memory_order_relaxed); } + +SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) { + std::lock_guard lock{mutex_}; + messages_.push_back(log_msg_buffer{msg}); +} + +SPDLOG_INLINE bool backtracer::empty() const { + std::lock_guard lock{mutex_}; + return messages_.empty(); +} + +// pop all items in the q and apply the given fun on each of them. +SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) { + std::lock_guard lock{mutex_}; + while (!messages_.empty()) { + auto &front_msg = messages_.front(); + fun(front_msg); + messages_.pop_front(); + } +} +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/backtracer.h b/vendor/opensource/log_lib/spdlog/details/backtracer.h new file mode 100755 index 0000000000000000000000000000000000000000..541339cdc32caba890fc0a2a4e8728085099de76 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/backtracer.h @@ -0,0 +1,45 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include +#include + +// Store log messages in circular buffer. +// Useful for storing debug data in case of error/warning happens. + +namespace spdlog { +namespace details { +class SPDLOG_API backtracer { + mutable std::mutex mutex_; + std::atomic enabled_{false}; + circular_q messages_; + +public: + backtracer() = default; + backtracer(const backtracer &other); + + backtracer(backtracer &&other) SPDLOG_NOEXCEPT; + backtracer &operator=(backtracer other); + + void enable(size_t size); + void disable(); + bool enabled() const; + void push_back(const log_msg &msg); + bool empty() const; + + // pop all items in the q and apply the given fun on each of them. + void foreach_pop(std::function fun); +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "backtracer-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/circular_q.h b/vendor/opensource/log_lib/spdlog/details/circular_q.h new file mode 100755 index 0000000000000000000000000000000000000000..29e9d255f4f4c5ffba08f3ccb234688698035be7 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/circular_q.h @@ -0,0 +1,115 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// circular q view of std::vector. +#pragma once + +#include +#include + +#include "spdlog/common.h" + +namespace spdlog { +namespace details { +template +class circular_q { + size_t max_items_ = 0; + typename std::vector::size_type head_ = 0; + typename std::vector::size_type tail_ = 0; + size_t overrun_counter_ = 0; + std::vector v_; + +public: + using value_type = T; + + // empty ctor - create a disabled queue with no elements allocated at all + circular_q() = default; + + explicit circular_q(size_t max_items) + : max_items_(max_items + 1) // one item is reserved as marker for full q + , + v_(max_items_) {} + + circular_q(const circular_q &) = default; + circular_q &operator=(const circular_q &) = default; + + // move cannot be default, + // since we need to reset head_, tail_, etc to zero in the moved object + circular_q(circular_q &&other) SPDLOG_NOEXCEPT { copy_moveable(std::move(other)); } + + circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT { + copy_moveable(std::move(other)); + return *this; + } + + // push back, overrun (oldest) item if no room left + void push_back(T &&item) { + if (max_items_ > 0) { + v_[tail_] = std::move(item); + tail_ = (tail_ + 1) % max_items_; + + if (tail_ == head_) // overrun last item if full + { + head_ = (head_ + 1) % max_items_; + ++overrun_counter_; + } + } + } + + // Return reference to the front item. + // If there are no elements in the container, the behavior is undefined. + const T &front() const { return v_[head_]; } + + T &front() { return v_[head_]; } + + // Return number of elements actually stored + size_t size() const { + if (tail_ >= head_) { + return tail_ - head_; + } else { + return max_items_ - (head_ - tail_); + } + } + + // Return const reference to item by index. + // If index is out of range 0…size()-1, the behavior is undefined. + const T &at(size_t i) const { + assert(i < size()); + return v_[(head_ + i) % max_items_]; + } + + // Pop item from front. + // If there are no elements in the container, the behavior is undefined. + void pop_front() { head_ = (head_ + 1) % max_items_; } + + bool empty() const { return tail_ == head_; } + + bool full() const { + // head is ahead of the tail by 1 + if (max_items_ > 0) { + return ((tail_ + 1) % max_items_) == head_; + } + return false; + } + + size_t overrun_counter() const { return overrun_counter_; } + + void reset_overrun_counter() { overrun_counter_ = 0; } + +private: + // copy from other&& and reset it to disabled state + void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT { + max_items_ = other.max_items_; + head_ = other.head_; + tail_ = other.tail_; + overrun_counter_ = other.overrun_counter_; + v_ = std::move(other.v_); + + // put &&other in disabled, but valid state + other.max_items_ = 0; + other.head_ = other.tail_ = 0; + other.overrun_counter_ = 0; + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/console_globals.h b/vendor/opensource/log_lib/spdlog/details/console_globals.h new file mode 100755 index 0000000000000000000000000000000000000000..9c552106a4e3c3cdfab1cddb857969c126f5a024 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/console_globals.h @@ -0,0 +1,28 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { + +struct console_mutex { + using mutex_t = std::mutex; + static mutex_t &mutex() { + static mutex_t s_mutex; + return s_mutex; + } +}; + +struct console_nullmutex { + using mutex_t = null_mutex; + static mutex_t &mutex() { + static mutex_t s_mutex; + return s_mutex; + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/file_helper-inl.h b/vendor/opensource/log_lib/spdlog/details/file_helper-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..8742b96c7dce89b95f2356242919904e8c29d5c5 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/file_helper-inl.h @@ -0,0 +1,153 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers) + : event_handlers_(event_handlers) {} + +SPDLOG_INLINE file_helper::~file_helper() { close(); } + +SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) { + close(); + filename_ = fname; + + auto *mode = SPDLOG_FILENAME_T("ab"); + auto *trunc_mode = SPDLOG_FILENAME_T("wb"); + + if (event_handlers_.before_open) { + event_handlers_.before_open(filename_); + } + for (int tries = 0; tries < open_tries_; ++tries) { + // create containing folder if not exists already. + os::create_dir(os::dir_name(fname)); + if (truncate) { + // Truncate by opening-and-closing a tmp file in "wb" mode, always + // opening the actual log-we-write-to in "ab" mode, since that + // interacts more politely with eternal processes that might + // rotate/truncate the file underneath us. + std::FILE *tmp; + if (os::fopen_s(&tmp, fname, trunc_mode)) { + continue; + } + std::fclose(tmp); + } + if (!os::fopen_s(&fd_, fname, mode)) { + if (event_handlers_.after_open) { + event_handlers_.after_open(filename_, fd_); + } + return; + } + + details::os::sleep_for_millis(open_interval_); + } + + throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", + errno); +} + +SPDLOG_INLINE void file_helper::reopen(bool truncate) { + if (filename_.empty()) { + throw_spdlog_ex("Failed re opening file - was not opened before"); + } + this->open(filename_, truncate); +} + +SPDLOG_INLINE void file_helper::flush() { + if (std::fflush(fd_) != 0) { + throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE void file_helper::sync() { + if (!os::fsync(fd_)) { + throw_spdlog_ex("Failed to fsync file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE void file_helper::close() { + if (fd_ != nullptr) { + if (event_handlers_.before_close) { + event_handlers_.before_close(filename_, fd_); + } + + std::fclose(fd_); + fd_ = nullptr; + + if (event_handlers_.after_close) { + event_handlers_.after_close(filename_); + } + } +} + +SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) { + if (fd_ == nullptr) return; + size_t msg_size = buf.size(); + auto data = buf.data(); + + if (!details::os::fwrite_bytes(data, msg_size, fd_)) { + throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE size_t file_helper::size() const { + if (fd_ == nullptr) { + throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)); + } + return os::filesize(fd_); +} + +SPDLOG_INLINE const filename_t &file_helper::filename() const { return filename_; } + +// +// return file path and its extension: +// +// "mylog.txt" => ("mylog", ".txt") +// "mylog" => ("mylog", "") +// "mylog." => ("mylog.", "") +// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") +// +// the starting dot in filenames is ignored (hidden files): +// +// ".mylog" => (".mylog". "") +// "my_folder/.mylog" => ("my_folder/.mylog", "") +// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") +SPDLOG_INLINE std::tuple file_helper::split_by_extension( + const filename_t &fname) { + auto ext_index = fname.rfind('.'); + + // no valid extension found - return whole path and empty string as + // extension + if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) { + return std::make_tuple(fname, filename_t()); + } + + // treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" + auto folder_index = fname.find_last_of(details::os::folder_seps_filename); + if (folder_index != filename_t::npos && folder_index >= ext_index - 1) { + return std::make_tuple(fname, filename_t()); + } + + // finally - return a valid base and extension tuple + return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); +} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/file_helper.h b/vendor/opensource/log_lib/spdlog/details/file_helper.h new file mode 100755 index 0000000000000000000000000000000000000000..f0e5d180e331a4e0477469100495a1ea0ffa4e87 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/file_helper.h @@ -0,0 +1,61 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { + +// Helper class for file sinks. +// When failing to open a file, retry several times(5) with a delay interval(10 ms). +// Throw spdlog_ex exception on errors. + +class SPDLOG_API file_helper { +public: + file_helper() = default; + explicit file_helper(const file_event_handlers &event_handlers); + + file_helper(const file_helper &) = delete; + file_helper &operator=(const file_helper &) = delete; + ~file_helper(); + + void open(const filename_t &fname, bool truncate = false); + void reopen(bool truncate); + void flush(); + void sync(); + void close(); + void write(const memory_buf_t &buf); + size_t size() const; + const filename_t &filename() const; + + // + // return file path and its extension: + // + // "mylog.txt" => ("mylog", ".txt") + // "mylog" => ("mylog", "") + // "mylog." => ("mylog.", "") + // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") + // + // the starting dot in filenames is ignored (hidden files): + // + // ".mylog" => (".mylog". "") + // "my_folder/.mylog" => ("my_folder/.mylog", "") + // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") + static std::tuple split_by_extension(const filename_t &fname); + +private: + const int open_tries_ = 5; + const unsigned int open_interval_ = 10; + std::FILE *fd_{nullptr}; + filename_t filename_; + file_event_handlers event_handlers_; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "file_helper-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/fmt_helper.h b/vendor/opensource/log_lib/spdlog/details/fmt_helper.h new file mode 100755 index 0000000000000000000000000000000000000000..61306003b2107e9e61e7aaaf212afc64e7ede39f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/fmt_helper.h @@ -0,0 +1,141 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +#pragma once + +#include +#include +#include +#include +#include + +#ifdef SPDLOG_USE_STD_FORMAT + #include + #include +#endif + +// Some fmt helpers to efficiently format and pad ints and strings +namespace spdlog { +namespace details { +namespace fmt_helper { + +inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest) { + auto *buf_ptr = view.data(); + dest.append(buf_ptr, buf_ptr + view.size()); +} + +#ifdef SPDLOG_USE_STD_FORMAT +template +inline void append_int(T n, memory_buf_t &dest) { + // Buffer should be large enough to hold all digits (digits10 + 1) and a sign + SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits::digits10 + 2; + char buf[BUF_SIZE]; + + auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10); + if (ec == std::errc()) { + dest.append(buf, ptr); + } else { + throw_spdlog_ex("Failed to format int", static_cast(ec)); + } +} +#else +template +inline void append_int(T n, memory_buf_t &dest) { + fmt::format_int i(n); + dest.append(i.data(), i.data() + i.size()); +} +#endif + +template +SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n) { + // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912 + unsigned int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} + +template +inline unsigned int count_digits(T n) { + using count_type = + typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type; +#ifdef SPDLOG_USE_STD_FORMAT + return count_digits_fallback(static_cast(n)); +#else + return static_cast(fmt:: + // fmt 7.0.0 renamed the internal namespace to detail. + // See: https://github.com/fmtlib/fmt/issues/1538 + #if FMT_VERSION < 70000 + internal + #else + detail + #endif + ::count_digits(static_cast(n))); +#endif +} + +inline void pad2(int n, memory_buf_t &dest) { + if (n >= 0 && n < 100) // 0-99 + { + dest.push_back(static_cast('0' + n / 10)); + dest.push_back(static_cast('0' + n % 10)); + } else // unlikely, but just in case, let fmt deal with it + { + fmt_lib::format_to(std::back_inserter(dest), SPDLOG_FMT_STRING("{:02}"), n); + } +} + +template +inline void pad_uint(T n, unsigned int width, memory_buf_t &dest) { + static_assert(std::is_unsigned::value, "pad_uint must get unsigned T"); + for (auto digits = count_digits(n); digits < width; digits++) { + dest.push_back('0'); + } + append_int(n, dest); +} + +template +inline void pad3(T n, memory_buf_t &dest) { + static_assert(std::is_unsigned::value, "pad3 must get unsigned T"); + if (n < 1000) { + dest.push_back(static_cast(n / 100 + '0')); + n = n % 100; + dest.push_back(static_cast((n / 10) + '0')); + dest.push_back(static_cast((n % 10) + '0')); + } else { + append_int(n, dest); + } +} + +template +inline void pad6(T n, memory_buf_t &dest) { + pad_uint(n, 6, dest); +} + +template +inline void pad9(T n, memory_buf_t &dest) { + pad_uint(n, 9, dest); +} + +// return fraction of a second of the given time_point. +// e.g. +// fraction(tp) -> will return the millis part of the second +template +inline ToDuration time_fraction(log_clock::time_point tp) { + using std::chrono::duration_cast; + using std::chrono::seconds; + auto duration = tp.time_since_epoch(); + auto secs = duration_cast(duration); + return duration_cast(duration) - duration_cast(secs); +} + +} // namespace fmt_helper +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/log_msg-inl.h b/vendor/opensource/log_lib/spdlog/details/log_msg-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..aa3a957682e5dfecd132a3e2e7667b239bfb06ed --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/log_msg-inl.h @@ -0,0 +1,44 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, + spdlog::source_loc loc, + string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : logger_name(a_logger_name), + level(lvl), + time(log_time) +#ifndef SPDLOG_NO_THREAD_ID + , + thread_id(os::thread_id()) +#endif + , + source(loc), + payload(msg) { +} + +SPDLOG_INLINE log_msg::log_msg(spdlog::source_loc loc, + string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : log_msg(os::now(), loc, a_logger_name, lvl, msg) {} + +SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) {} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/log_msg.h b/vendor/opensource/log_lib/spdlog/details/log_msg.h new file mode 100755 index 0000000000000000000000000000000000000000..87df1e833277a74eac4729fd4c4d2ce9ebf75ab9 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/log_msg.h @@ -0,0 +1,40 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { +struct SPDLOG_API log_msg { + log_msg() = default; + log_msg(log_clock::time_point log_time, + source_loc loc, + string_view_t logger_name, + level::level_enum lvl, + string_view_t msg); + log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); + log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); + log_msg(const log_msg &other) = default; + log_msg &operator=(const log_msg &other) = default; + + string_view_t logger_name; + level::level_enum level{level::off}; + log_clock::time_point time; + size_t thread_id{0}; + + // wrapping the formatted text with color (updated by pattern_formatter). + mutable size_t color_range_start{0}; + mutable size_t color_range_end{0}; + + source_loc source; + string_view_t payload; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "log_msg-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/log_msg_buffer-inl.h b/vendor/opensource/log_lib/spdlog/details/log_msg_buffer-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..2eb242859ea2ca76ba8239b6c410bce42726e7f2 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/log_msg_buffer-inl.h @@ -0,0 +1,54 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +namespace spdlog { +namespace details { + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) + : log_msg{orig_msg} { + buffer.append(logger_name.begin(), logger_name.end()); + buffer.append(payload.begin(), payload.end()); + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) + : log_msg{other} { + buffer.append(logger_name.begin(), logger_name.end()); + buffer.append(payload.begin(), payload.end()); + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT + : log_msg{other}, + buffer{std::move(other.buffer)} { + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) { + log_msg::operator=(other); + buffer.clear(); + buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); + update_string_views(); + return *this; +} + +SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT { + log_msg::operator=(other); + buffer = std::move(other.buffer); + update_string_views(); + return *this; +} + +SPDLOG_INLINE void log_msg_buffer::update_string_views() { + logger_name = string_view_t{buffer.data(), logger_name.size()}; + payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; +} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/log_msg_buffer.h b/vendor/opensource/log_lib/spdlog/details/log_msg_buffer.h new file mode 100755 index 0000000000000000000000000000000000000000..1143b3ba45062f38721923323a8d321360d7fbad --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/log_msg_buffer.h @@ -0,0 +1,32 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include + +namespace spdlog { +namespace details { + +// Extend log_msg with internal buffer to store its payload. +// This is needed since log_msg holds string_views that points to stack data. + +class SPDLOG_API log_msg_buffer : public log_msg { + memory_buf_t buffer; + void update_string_views(); + +public: + log_msg_buffer() = default; + explicit log_msg_buffer(const log_msg &orig_msg); + log_msg_buffer(const log_msg_buffer &other); + log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT; + log_msg_buffer &operator=(const log_msg_buffer &other); + log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT; +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "log_msg_buffer-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/mpmc_blocking_q.h b/vendor/opensource/log_lib/spdlog/details/mpmc_blocking_q.h new file mode 100755 index 0000000000000000000000000000000000000000..5848cca83f9e23f14eb76195be35e1ac03dd0686 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/mpmc_blocking_q.h @@ -0,0 +1,177 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// multi producer-multi consumer blocking queue. +// enqueue(..) - will block until room found to put the new message. +// enqueue_nowait(..) - will return immediately with false if no room left in +// the queue. +// dequeue_for(..) - will block until the queue is not empty or timeout have +// passed. + +#include + +#include +#include +#include + +namespace spdlog { +namespace details { + +template +class mpmc_blocking_queue { +public: + using item_type = T; + explicit mpmc_blocking_queue(size_t max_items) + : q_(max_items) {} + +#ifndef __MINGW32__ + // try to enqueue and block if no room left + void enqueue(T &&item) { + { + std::unique_lock lock(queue_mutex_); + pop_cv_.wait(lock, [this] { return !this->q_.full(); }); + q_.push_back(std::move(item)); + } + push_cv_.notify_one(); + } + + // enqueue immediately. overrun oldest message in the queue if no room left. + void enqueue_nowait(T &&item) { + { + std::unique_lock lock(queue_mutex_); + q_.push_back(std::move(item)); + } + push_cv_.notify_one(); + } + + void enqueue_if_have_room(T &&item) { + bool pushed = false; + { + std::unique_lock lock(queue_mutex_); + if (!q_.full()) { + q_.push_back(std::move(item)); + pushed = true; + } + } + + if (pushed) { + push_cv_.notify_one(); + } else { + ++discard_counter_; + } + } + + // dequeue with a timeout. + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { + { + std::unique_lock lock(queue_mutex_); + if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) { + return false; + } + popped_item = std::move(q_.front()); + q_.pop_front(); + } + pop_cv_.notify_one(); + return true; + } + + // blocking dequeue without a timeout. + void dequeue(T &popped_item) { + { + std::unique_lock lock(queue_mutex_); + push_cv_.wait(lock, [this] { return !this->q_.empty(); }); + popped_item = std::move(q_.front()); + q_.pop_front(); + } + pop_cv_.notify_one(); + } + +#else + // apparently mingw deadlocks if the mutex is released before cv.notify_one(), + // so release the mutex at the very end each function. + + // try to enqueue and block if no room left + void enqueue(T &&item) { + std::unique_lock lock(queue_mutex_); + pop_cv_.wait(lock, [this] { return !this->q_.full(); }); + q_.push_back(std::move(item)); + push_cv_.notify_one(); + } + + // enqueue immediately. overrun oldest message in the queue if no room left. + void enqueue_nowait(T &&item) { + std::unique_lock lock(queue_mutex_); + q_.push_back(std::move(item)); + push_cv_.notify_one(); + } + + void enqueue_if_have_room(T &&item) { + bool pushed = false; + std::unique_lock lock(queue_mutex_); + if (!q_.full()) { + q_.push_back(std::move(item)); + pushed = true; + } + + if (pushed) { + push_cv_.notify_one(); + } else { + ++discard_counter_; + } + } + + // dequeue with a timeout. + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { + std::unique_lock lock(queue_mutex_); + if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) { + return false; + } + popped_item = std::move(q_.front()); + q_.pop_front(); + pop_cv_.notify_one(); + return true; + } + + // blocking dequeue without a timeout. + void dequeue(T &popped_item) { + std::unique_lock lock(queue_mutex_); + push_cv_.wait(lock, [this] { return !this->q_.empty(); }); + popped_item = std::move(q_.front()); + q_.pop_front(); + pop_cv_.notify_one(); + } + +#endif + + size_t overrun_counter() { + std::lock_guard lock(queue_mutex_); + return q_.overrun_counter(); + } + + size_t discard_counter() { return discard_counter_.load(std::memory_order_relaxed); } + + size_t size() { + std::lock_guard lock(queue_mutex_); + return q_.size(); + } + + void reset_overrun_counter() { + std::lock_guard lock(queue_mutex_); + q_.reset_overrun_counter(); + } + + void reset_discard_counter() { discard_counter_.store(0, std::memory_order_relaxed); } + +private: + std::mutex queue_mutex_; + std::condition_variable push_cv_; + std::condition_variable pop_cv_; + spdlog::details::circular_q q_; + std::atomic discard_counter_{0}; +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/null_mutex.h b/vendor/opensource/log_lib/spdlog/details/null_mutex.h new file mode 100755 index 0000000000000000000000000000000000000000..e3b32204158df4b4a6c5d40953cb22cd497f6212 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/null_mutex.h @@ -0,0 +1,35 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +// null, no cost dummy "mutex" and dummy "atomic" int + +namespace spdlog { +namespace details { +struct null_mutex { + void lock() const {} + void unlock() const {} +}; + +struct null_atomic_int { + int value; + null_atomic_int() = default; + + explicit null_atomic_int(int new_value) + : value(new_value) {} + + int load(std::memory_order = std::memory_order_relaxed) const { return value; } + + void store(int new_value, std::memory_order = std::memory_order_relaxed) { value = new_value; } + + int exchange(int new_value, std::memory_order = std::memory_order_relaxed) { + std::swap(new_value, value); + return new_value; // return value before the call + } +}; + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/os-inl.h b/vendor/opensource/log_lib/spdlog/details/os-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..3aaa6b54513773f8436da8dfdef782c3b801b63e --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/os-inl.h @@ -0,0 +1,606 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include // for FlushFileBuffers + #include // for _get_osfhandle, _isatty, _fileno + #include // for _get_pid + + #ifdef __MINGW32__ + #include + #endif + + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES) + #include + #include + #endif + + #include // for _mkdir/_wmkdir + +#else // unix + + #include + #include + + #ifdef __linux__ + #include //Use gettid() syscall under linux to get thread id + + #elif defined(_AIX) + #include // for pthread_getthrds_np + + #elif defined(__DragonFly__) || defined(__FreeBSD__) + #include // for pthread_getthreadid_np + + #elif defined(__NetBSD__) + #include // for _lwp_self + + #elif defined(__sun) + #include // for thr_self + #endif + +#endif // unix + +#if defined __APPLE__ + #include +#endif + +#ifndef __has_feature // Clang - feature checking macros. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + +namespace spdlog { +namespace details { +namespace os { + +SPDLOG_INLINE spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT { +#if defined __linux__ && defined SPDLOG_CLOCK_COARSE + timespec ts; + ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); + return std::chrono::time_point( + std::chrono::duration_cast( + std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); + +#else + return log_clock::now(); +#endif +} +SPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + std::tm tm; + ::localtime_s(&tm, &time_tt); +#else + std::tm tm; + ::localtime_r(&time_tt, &tm); +#endif + return tm; +} + +SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT { + std::time_t now_t = ::time(nullptr); + return localtime(now_t); +} + +SPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + std::tm tm; + ::gmtime_s(&tm, &time_tt); +#else + std::tm tm; + ::gmtime_r(&time_tt, &tm); +#endif + return tm; +} + +SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT { + std::time_t now_t = ::time(nullptr); + return gmtime(now_t); +} + +// fopen_s on non windows for writing +SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) { +#ifdef _WIN32 + #ifdef SPDLOG_WCHAR_FILENAMES + *fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + #else + *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + #endif + #if defined(SPDLOG_PREVENT_CHILD_FD) + if (*fp != nullptr) { + auto file_handle = reinterpret_cast(_get_osfhandle(::_fileno(*fp))); + if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) { + ::fclose(*fp); + *fp = nullptr; + } + } + #endif +#else // unix + #if defined(SPDLOG_PREVENT_CHILD_FD) + const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC; + const int fd = + ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644)); + if (fd == -1) { + return true; + } + *fp = ::fdopen(fd, mode.c_str()); + if (*fp == nullptr) { + ::close(fd); + } + #else + *fp = ::fopen((filename.c_str()), mode.c_str()); + #endif +#endif + + return *fp == nullptr; +} + +SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return ::_wremove(filename.c_str()); +#else + return std::remove(filename.c_str()); +#endif +} + +SPDLOG_INLINE int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT { + return path_exists(filename) ? remove(filename) : 0; +} + +SPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return ::_wrename(filename1.c_str(), filename2.c_str()); +#else + return std::rename(filename1.c_str(), filename2.c_str()); +#endif +} + +// Return true if path exists (file or directory) +SPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + struct _stat buffer; + #ifdef SPDLOG_WCHAR_FILENAMES + return (::_wstat(filename.c_str(), &buffer) == 0); + #else + return (::_stat(filename.c_str(), &buffer) == 0); + #endif +#else // common linux/unix all have the stat system call + struct stat buffer; + return (::stat(filename.c_str(), &buffer) == 0); +#endif +} + +#ifdef _MSC_VER + // avoid warning about unreachable statement at the end of filesize() + #pragma warning(push) + #pragma warning(disable : 4702) +#endif + +// Return file size according to open FILE* object +SPDLOG_INLINE size_t filesize(FILE *f) { + if (f == nullptr) { + throw_spdlog_ex("Failed getting file size. fd is null"); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + int fd = ::_fileno(f); + #if defined(_WIN64) // 64 bits + __int64 ret = ::_filelengthi64(fd); + if (ret >= 0) { + return static_cast(ret); + } + + #else // windows 32 bits + long ret = ::_filelength(fd); + if (ret >= 0) { + return static_cast(ret); + } + #endif + +#else // unix + // OpenBSD and AIX doesn't compile with :: before the fileno(..) + #if defined(__OpenBSD__) || defined(_AIX) + int fd = fileno(f); + #else + int fd = ::fileno(f); + #endif + // 64 bits(but not in osx, linux/musl or cygwin, where fstat64 is deprecated) + #if ((defined(__linux__) && defined(__GLIBC__)) || defined(__sun) || defined(_AIX)) && \ + (defined(__LP64__) || defined(_LP64)) + struct stat64 st; + if (::fstat64(fd, &st) == 0) { + return static_cast(st.st_size); + } + #else // other unix or linux 32 bits or cygwin + struct stat st; + if (::fstat(fd, &st) == 0) { + return static_cast(st.st_size); + } + #endif +#endif + throw_spdlog_ex("Failed getting file size from fd", errno); + return 0; // will not be reached. +} + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +// Return utc offset in minutes or throw spdlog_ex on failure +SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm) { +#ifdef _WIN32 + #if _WIN32_WINNT < _WIN32_WINNT_WS08 + TIME_ZONE_INFORMATION tzinfo; + auto rv = ::GetTimeZoneInformation(&tzinfo); + #else + DYNAMIC_TIME_ZONE_INFORMATION tzinfo; + auto rv = ::GetDynamicTimeZoneInformation(&tzinfo); + #endif + if (rv == TIME_ZONE_ID_INVALID) throw_spdlog_ex("Failed getting timezone info. ", errno); + + int offset = -tzinfo.Bias; + if (tm.tm_isdst) { + offset -= tzinfo.DaylightBias; + } else { + offset -= tzinfo.StandardBias; + } + return offset; +#else + + #if defined(sun) || defined(__sun) || defined(_AIX) || \ + (defined(__NEWLIB__) && !defined(__TM_GMTOFF)) || \ + (!defined(__APPLE__) && !defined(_BSD_SOURCE) && !defined(_GNU_SOURCE) && \ + (!defined(_POSIX_VERSION) || (_POSIX_VERSION < 202405L))) + // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris + struct helper { + static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), + const std::tm &gmtm = details::os::gmtime()) { + int local_year = localtm.tm_year + (1900 - 1); + int gmt_year = gmtm.tm_year + (1900 - 1); + + long int days = ( + // difference in day of year + localtm.tm_yday - + gmtm.tm_yday + + // + intervening leap days + + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) + + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) + + // + difference in years * 365 */ + + static_cast(local_year - gmt_year) * 365); + + long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); + long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); + long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); + + return secs; + } + }; + + auto offset_seconds = helper::calculate_gmt_offset(tm); + #else + auto offset_seconds = tm.tm_gmtoff; + #endif + + return static_cast(offset_seconds / 60); +#endif +} + +// Return current thread id as size_t +// It exists because the std::this_thread::get_id() is much slower(especially +// under VS 2013) +SPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return static_cast(::GetCurrentThreadId()); +#elif defined(__linux__) + #if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) + #define SYS_gettid __NR_gettid + #endif + return static_cast(::syscall(SYS_gettid)); +#elif defined(_AIX) + struct __pthrdsinfo buf; + int reg_size = 0; + pthread_t pt = pthread_self(); + int retval = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &buf, sizeof(buf), NULL, ®_size); + int tid = (!retval) ? buf.__pi_tid : 0; + return static_cast(tid); +#elif defined(__DragonFly__) || defined(__FreeBSD__) + return static_cast(::pthread_getthreadid_np()); +#elif defined(__NetBSD__) + return static_cast(::_lwp_self()); +#elif defined(__OpenBSD__) + return static_cast(::getthrid()); +#elif defined(__sun) + return static_cast(::thr_self()); +#elif __APPLE__ + uint64_t tid; + // There is no pthread_threadid_np prior to Mac OS X 10.6, and it is not supported on any PPC, + // including 10.6.8 Rosetta. __POWERPC__ is Apple-specific define encompassing ppc and ppc64. + #ifdef MAC_OS_X_VERSION_MAX_ALLOWED + { + #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) || defined(__POWERPC__) + tid = pthread_mach_thread_np(pthread_self()); + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + if (&pthread_threadid_np) { + pthread_threadid_np(nullptr, &tid); + } else { + tid = pthread_mach_thread_np(pthread_self()); + } + #else + pthread_threadid_np(nullptr, &tid); + #endif + } + #else + pthread_threadid_np(nullptr, &tid); + #endif + return static_cast(tid); +#else // Default to standard C++11 (other Unix) + return static_cast(std::hash()(std::this_thread::get_id())); +#endif +} + +// Return current thread id as size_t (from thread local storage) +SPDLOG_INLINE size_t thread_id() SPDLOG_NOEXCEPT { +#if defined(SPDLOG_NO_TLS) + return _thread_id(); +#else // cache thread id in tls + static thread_local const size_t tid = _thread_id(); + return tid; +#endif +} + +// This is avoid msvc issue in sleep_for that happens if the clock changes. +// See https://github.com/gabime/spdlog/issues/609 +SPDLOG_INLINE void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT { +#if defined(_WIN32) + ::Sleep(milliseconds); +#else + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); +#endif +} + +// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) { + memory_buf_t buf; + wstr_to_utf8buf(filename, buf); + return SPDLOG_BUF_TO_STRING(buf); +} +#else +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) { return filename; } +#endif + +SPDLOG_INLINE int pid() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return conditional_static_cast(::GetCurrentProcessId()); +#else + return conditional_static_cast(::getpid()); +#endif +} + +// Determine if the terminal supports colors +// Based on: https://github.com/agauniyal/rang/ +SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return true; +#else + + static const bool result = []() { + const char *env_colorterm_p = std::getenv("COLORTERM"); + if (env_colorterm_p != nullptr) { + return true; + } + + static constexpr std::array terms = { + {"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", + "putty", "rxvt", "screen", "vt100", "xterm", "alacritty", "vt102"}}; + + const char *env_term_p = std::getenv("TERM"); + if (env_term_p == nullptr) { + return false; + } + + return std::any_of(terms.begin(), terms.end(), [&](const char *term) { + return std::strstr(env_term_p, term) != nullptr; + }); + }(); + + return result; +#endif +} + +// Determine if the terminal attached +// Source: https://github.com/agauniyal/rang/ +SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return ::_isatty(_fileno(file)) != 0; +#else + return ::isatty(fileno(file)) != 0; +#endif +} + +#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) +SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) { + if (wstr.size() > static_cast((std::numeric_limits::max)()) / 4 - 1) { + throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8"); + } + + int wstr_size = static_cast(wstr.size()); + if (wstr_size == 0) { + target.resize(0); + return; + } + + int result_size = static_cast(target.capacity()); + if ((wstr_size + 1) * 4 > result_size) { + result_size = + ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, NULL, 0, NULL, NULL); + } + + if (result_size > 0) { + target.resize(result_size); + result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, target.data(), + result_size, NULL, NULL); + + if (result_size > 0) { + target.resize(result_size); + return; + } + } + + throw_spdlog_ex( + fmt_lib::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); +} + +SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) { + if (str.size() > static_cast((std::numeric_limits::max)()) - 1) { + throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16"); + } + + int str_size = static_cast(str.size()); + if (str_size == 0) { + target.resize(0); + return; + } + + // find the size to allocate for the result buffer + int result_size = ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str_size, NULL, 0); + + if (result_size > 0) { + target.resize(result_size); + result_size = + ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str_size, target.data(), result_size); + if (result_size > 0) { + assert(result_size == target.size()); + return; + } + } + + throw_spdlog_ex( + fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); +} +#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && + // defined(_WIN32) + +// return true on success +static SPDLOG_INLINE bool mkdir_(const filename_t &path) { +#ifdef _WIN32 + #ifdef SPDLOG_WCHAR_FILENAMES + return ::_wmkdir(path.c_str()) == 0; + #else + return ::_mkdir(path.c_str()) == 0; + #endif +#else + return ::mkdir(path.c_str(), mode_t(0755)) == 0; +#endif +} + +// create the given directory - and all directories leading to it +// return true on success or if the directory already exists +SPDLOG_INLINE bool create_dir(const filename_t &path) { + if (path_exists(path)) { + return true; + } + + if (path.empty()) { + return false; + } + + size_t search_offset = 0; + do { + auto token_pos = path.find_first_of(folder_seps_filename, search_offset); + // treat the entire path as a folder if no folder separator not found + if (token_pos == filename_t::npos) { + token_pos = path.size(); + } + + auto subdir = path.substr(0, token_pos); +#ifdef _WIN32 + // if subdir is just a drive letter, add a slash e.g. "c:"=>"c:\", + // otherwise path_exists(subdir) returns false (issue #3079) + const bool is_drive = subdir.length() == 2 && subdir[1] == ':'; + if (is_drive) { + subdir += '\\'; + token_pos++; + } +#endif + + if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir)) { + return false; // return error if failed creating dir + } + search_offset = token_pos + 1; + } while (search_offset < path.size()); + + return true; +} + +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +SPDLOG_INLINE filename_t dir_name(const filename_t &path) { + auto pos = path.find_last_of(folder_seps_filename); + return pos != filename_t::npos ? path.substr(0, pos) : filename_t{}; +} + +std::string SPDLOG_INLINE getenv(const char *field) { +#if defined(_MSC_VER) + #if defined(__cplusplus_winrt) + return std::string{}; // not supported under uwp + #else + size_t len = 0; + char buf[128]; + bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0; + return ok ? buf : std::string{}; + #endif +#else // revert to getenv + char *buf = ::getenv(field); + return buf ? buf : std::string{}; +#endif +} + +// Do fsync by FILE handlerpointer +// Return true on success +SPDLOG_INLINE bool fsync(FILE *fp) { +#ifdef _WIN32 + return FlushFileBuffers(reinterpret_cast(_get_osfhandle(_fileno(fp)))) != 0; +#else + return ::fsync(fileno(fp)) == 0; +#endif +} + +// Do non-locking fwrite if possible by the os or use the regular locking fwrite +// Return true on success. +SPDLOG_INLINE bool fwrite_bytes(const void *ptr, const size_t n_bytes, FILE *fp) { +#if defined(_WIN32) && defined(SPDLOG_FWRITE_UNLOCKED) + return _fwrite_nolock(ptr, 1, n_bytes, fp) == n_bytes; +#elif defined(SPDLOG_FWRITE_UNLOCKED) + return ::fwrite_unlocked(ptr, 1, n_bytes, fp) == n_bytes; +#else + return std::fwrite(ptr, 1, n_bytes, fp) == n_bytes; +#endif +} + +} // namespace os +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/os.h b/vendor/opensource/log_lib/spdlog/details/os.h new file mode 100755 index 0000000000000000000000000000000000000000..5fd12bac1ea06c16dfe5df209424e4e1d637c7d9 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/os.h @@ -0,0 +1,127 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include // std::time_t +#include + +namespace spdlog { +namespace details { +namespace os { + +SPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT; + +// eol definition +#if !defined(SPDLOG_EOL) + #ifdef _WIN32 + #define SPDLOG_EOL "\r\n" + #else + #define SPDLOG_EOL "\n" + #endif +#endif + +SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; + +// folder separator +#if !defined(SPDLOG_FOLDER_SEPS) + #ifdef _WIN32 + #define SPDLOG_FOLDER_SEPS "\\/" + #else + #define SPDLOG_FOLDER_SEPS "/" + #endif +#endif + +SPDLOG_CONSTEXPR static const char folder_seps[] = SPDLOG_FOLDER_SEPS; +SPDLOG_CONSTEXPR static const filename_t::value_type folder_seps_filename[] = + SPDLOG_FILENAME_T(SPDLOG_FOLDER_SEPS); + +// fopen_s on non windows for writing +SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); + +// Remove filename. return 0 on success +SPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT; + +// Remove file if exists. return 0 on success +// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread) +SPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; + +SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; + +// Return if file exists. +SPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; + +// Return file size according to open FILE* object +SPDLOG_API size_t filesize(FILE *f); + +// Return utc offset in minutes or throw spdlog_ex on failure +SPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime()); + +// Return current thread id as size_t +// It exists because the std::this_thread::get_id() is much slower(especially +// under VS 2013) +SPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT; + +// Return current thread id as size_t (from thread local storage) +SPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT; + +// This is avoid msvc issue in sleep_for that happens if the clock changes. +// See https://github.com/gabime/spdlog/issues/609 +SPDLOG_API void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT; + +SPDLOG_API std::string filename_to_str(const filename_t &filename); + +SPDLOG_API int pid() SPDLOG_NOEXCEPT; + +// Determine if the terminal supports colors +// Source: https://github.com/agauniyal/rang/ +SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT; + +// Determine if the terminal attached +// Source: https://github.com/agauniyal/rang/ +SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; + +#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) +SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); + +SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target); +#endif + +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +SPDLOG_API filename_t dir_name(const filename_t &path); + +// Create a dir from the given path. +// Return true if succeeded or if this dir already exists. +SPDLOG_API bool create_dir(const filename_t &path); + +// non thread safe, cross platform getenv/getenv_s +// return empty string if field not found +SPDLOG_API std::string getenv(const char *field); + +// Do fsync by FILE objectpointer. +// Return true on success. +SPDLOG_API bool fsync(FILE *fp); + +// Do non-locking fwrite if possible by the os or use the regular locking fwrite +// Return true on success. +SPDLOG_API bool fwrite_bytes(const void *ptr, const size_t n_bytes, FILE *fp); + +} // namespace os +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "os-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/periodic_worker-inl.h b/vendor/opensource/log_lib/spdlog/details/periodic_worker-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..18f11fbec8cce92f47f145f1fa74cc22fca29464 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/periodic_worker-inl.h @@ -0,0 +1,26 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +namespace spdlog { +namespace details { + +// stop the worker thread and join it +SPDLOG_INLINE periodic_worker::~periodic_worker() { + if (worker_thread_.joinable()) { + { + std::lock_guard lock(mutex_); + active_ = false; + } + cv_.notify_one(); + worker_thread_.join(); + } +} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/periodic_worker.h b/vendor/opensource/log_lib/spdlog/details/periodic_worker.h new file mode 100755 index 0000000000000000000000000000000000000000..d647b66ee174ab7b706ae3c984b7cf37ff5221c5 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/periodic_worker.h @@ -0,0 +1,58 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// periodic worker thread - periodically executes the given callback function. +// +// RAII over the owned thread: +// creates the thread on construction. +// stops and joins the thread on destruction (if the thread is executing a callback, wait for it +// to finish first). + +#include +#include +#include +#include +#include +namespace spdlog { +namespace details { + +class SPDLOG_API periodic_worker { +public: + template + periodic_worker(const std::function &callback_fun, + std::chrono::duration interval) { + active_ = (interval > std::chrono::duration::zero()); + if (!active_) { + return; + } + + worker_thread_ = std::thread([this, callback_fun, interval]() { + for (;;) { + std::unique_lock lock(this->mutex_); + if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) { + return; // active_ == false, so exit this thread + } + callback_fun(); + } + }); + } + std::thread &get_thread() { return worker_thread_; } + periodic_worker(const periodic_worker &) = delete; + periodic_worker &operator=(const periodic_worker &) = delete; + // stop the worker thread and join it + ~periodic_worker(); + +private: + bool active_; + std::thread worker_thread_; + std::mutex mutex_; + std::condition_variable cv_; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "periodic_worker-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/registry-inl.h b/vendor/opensource/log_lib/spdlog/details/registry-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..4cbdeb753b314dbc00cd3befec763895d7eb51c0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/registry-inl.h @@ -0,0 +1,270 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include +#include + +#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER + // support for the default stdout color logger + #ifdef _WIN32 + #include + #else + #include + #endif +#endif // SPDLOG_DISABLE_DEFAULT_LOGGER + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE registry::registry() + : formatter_(new pattern_formatter()) { +#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER + // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows). + #ifdef _WIN32 + auto color_sink = std::make_shared(); + #else + auto color_sink = std::make_shared(); + #endif + + const char *default_logger_name = ""; + default_logger_ = std::make_shared(default_logger_name, std::move(color_sink)); + loggers_[default_logger_name] = default_logger_; + +#endif // SPDLOG_DISABLE_DEFAULT_LOGGER +} + +SPDLOG_INLINE registry::~registry() = default; + +SPDLOG_INLINE void registry::register_logger(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + register_logger_(std::move(new_logger)); +} + +SPDLOG_INLINE void registry::register_or_replace(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + register_or_replace_(std::move(new_logger)); +} + +SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + new_logger->set_formatter(formatter_->clone()); + + if (err_handler_) { + new_logger->set_error_handler(err_handler_); + } + + // set new level according to previously configured level or default level + auto it = log_levels_.find(new_logger->name()); + auto new_level = it != log_levels_.end() ? it->second : global_log_level_; + new_logger->set_level(new_level); + + new_logger->flush_on(flush_level_); + + if (backtrace_n_messages_ > 0) { + new_logger->enable_backtrace(backtrace_n_messages_); + } + + if (automatic_registration_) { + register_logger_(std::move(new_logger)); + } +} + +SPDLOG_INLINE std::shared_ptr registry::get(const std::string &logger_name) { + std::lock_guard lock(logger_map_mutex_); + auto found = loggers_.find(logger_name); + return found == loggers_.end() ? nullptr : found->second; +} + +SPDLOG_INLINE std::shared_ptr registry::default_logger() { + std::lock_guard lock(logger_map_mutex_); + return default_logger_; +} + +// Return raw ptr to the default logger. +// To be used directly by the spdlog default api (e.g. spdlog::info) +// This make the default API faster, but cannot be used concurrently with set_default_logger(). +// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. +SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get(); } + +// set default logger. +// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. +SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr new_default_logger) { + std::lock_guard lock(logger_map_mutex_); + if (new_default_logger != nullptr) { + loggers_[new_default_logger->name()] = new_default_logger; + } + default_logger_ = std::move(new_default_logger); +} + +SPDLOG_INLINE void registry::set_tp(std::shared_ptr tp) { + std::lock_guard lock(tp_mutex_); + tp_ = std::move(tp); +} + +SPDLOG_INLINE std::shared_ptr registry::get_tp() { + std::lock_guard lock(tp_mutex_); + return tp_; +} + +// Set global formatter. Each sink in each logger will get a clone of this object +SPDLOG_INLINE void registry::set_formatter(std::unique_ptr formatter) { + std::lock_guard lock(logger_map_mutex_); + formatter_ = std::move(formatter); + for (auto &l : loggers_) { + l.second->set_formatter(formatter_->clone()); + } +} + +SPDLOG_INLINE void registry::enable_backtrace(size_t n_messages) { + std::lock_guard lock(logger_map_mutex_); + backtrace_n_messages_ = n_messages; + + for (auto &l : loggers_) { + l.second->enable_backtrace(n_messages); + } +} + +SPDLOG_INLINE void registry::disable_backtrace() { + std::lock_guard lock(logger_map_mutex_); + backtrace_n_messages_ = 0; + for (auto &l : loggers_) { + l.second->disable_backtrace(); + } +} + +SPDLOG_INLINE void registry::set_level(level::level_enum log_level) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->set_level(log_level); + } + global_log_level_ = log_level; +} + +SPDLOG_INLINE void registry::flush_on(level::level_enum log_level) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->flush_on(log_level); + } + flush_level_ = log_level; +} + +SPDLOG_INLINE void registry::set_error_handler(err_handler handler) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->set_error_handler(handler); + } + err_handler_ = std::move(handler); +} + +SPDLOG_INLINE void registry::apply_all( + const std::function)> &fun) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + fun(l.second); + } +} + +SPDLOG_INLINE void registry::flush_all() { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->flush(); + } +} + +SPDLOG_INLINE void registry::drop(const std::string &logger_name) { + std::lock_guard lock(logger_map_mutex_); + auto is_default_logger = default_logger_ && default_logger_->name() == logger_name; + loggers_.erase(logger_name); + if (is_default_logger) { + default_logger_.reset(); + } +} + +SPDLOG_INLINE void registry::drop_all() { + std::lock_guard lock(logger_map_mutex_); + loggers_.clear(); + default_logger_.reset(); +} + +// clean all resources and threads started by the registry +SPDLOG_INLINE void registry::shutdown() { + { + std::lock_guard lock(flusher_mutex_); + periodic_flusher_.reset(); + } + + drop_all(); + + { + std::lock_guard lock(tp_mutex_); + tp_.reset(); + } +} + +SPDLOG_INLINE std::recursive_mutex ®istry::tp_mutex() { return tp_mutex_; } + +SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration) { + std::lock_guard lock(logger_map_mutex_); + automatic_registration_ = automatic_registration; +} + +SPDLOG_INLINE void registry::set_levels(log_levels levels, level::level_enum *global_level) { + std::lock_guard lock(logger_map_mutex_); + log_levels_ = std::move(levels); + auto global_level_requested = global_level != nullptr; + global_log_level_ = global_level_requested ? *global_level : global_log_level_; + + for (auto &logger : loggers_) { + auto logger_entry = log_levels_.find(logger.first); + if (logger_entry != log_levels_.end()) { + logger.second->set_level(logger_entry->second); + } else if (global_level_requested) { + logger.second->set_level(*global_level); + } + } +} + +SPDLOG_INLINE registry ®istry::instance() { + static registry s_instance; + return s_instance; +} + +SPDLOG_INLINE void registry::apply_logger_env_levels(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + auto it = log_levels_.find(new_logger->name()); + auto new_level = it != log_levels_.end() ? it->second : global_log_level_; + new_logger->set_level(new_level); +} + +SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name) { + if (loggers_.find(logger_name) != loggers_.end()) { + throw_spdlog_ex("logger with name '" + logger_name + "' already exists"); + } +} + +SPDLOG_INLINE void registry::register_logger_(std::shared_ptr new_logger) { + auto &logger_name = new_logger->name(); + throw_if_exists_(logger_name); + loggers_[logger_name] = std::move(new_logger); +} + +SPDLOG_INLINE void registry::register_or_replace_(std::shared_ptr new_logger) { + loggers_[new_logger->name()] = std::move(new_logger); +} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/registry.h b/vendor/opensource/log_lib/spdlog/details/registry.h new file mode 100755 index 0000000000000000000000000000000000000000..72c70b82bf7c79713dd5c0cb157e60a6dc486b59 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/registry.h @@ -0,0 +1,131 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Loggers registry of unique name->logger pointer +// An attempt to create a logger with an already existing name will result with spdlog_ex exception. +// If user requests a non existing logger, nullptr will be returned +// This class is thread safe + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +class logger; + +namespace details { +class thread_pool; + +class SPDLOG_API registry { +public: + using log_levels = std::unordered_map; + registry(const registry &) = delete; + registry &operator=(const registry &) = delete; + + void register_logger(std::shared_ptr new_logger); + void register_or_replace(std::shared_ptr new_logger); + void initialize_logger(std::shared_ptr new_logger); + std::shared_ptr get(const std::string &logger_name); + std::shared_ptr default_logger(); + + // Return raw ptr to the default logger. + // To be used directly by the spdlog default api (e.g. spdlog::info) + // This make the default API faster, but cannot be used concurrently with set_default_logger(). + // e.g do not call set_default_logger() from one thread while calling spdlog::info() from + // another. + logger *get_default_raw(); + + // set default logger and add it to the registry if not registered already. + // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. + // Note: Make sure to unregister it when no longer needed or before calling again with a new + // logger. + void set_default_logger(std::shared_ptr new_default_logger); + + void set_tp(std::shared_ptr tp); + + std::shared_ptr get_tp(); + + // Set global formatter. Each sink in each logger will get a clone of this object + void set_formatter(std::unique_ptr formatter); + + void enable_backtrace(size_t n_messages); + + void disable_backtrace(); + + void set_level(level::level_enum log_level); + + void flush_on(level::level_enum log_level); + + template + void flush_every(std::chrono::duration interval) { + std::lock_guard lock(flusher_mutex_); + auto clbk = [this]() { this->flush_all(); }; + periodic_flusher_ = details::make_unique(clbk, interval); + } + + std::unique_ptr &get_flusher() { + std::lock_guard lock(flusher_mutex_); + return periodic_flusher_; + } + + void set_error_handler(err_handler handler); + + void apply_all(const std::function)> &fun); + + void flush_all(); + + void drop(const std::string &logger_name); + + void drop_all(); + + // clean all resources and threads started by the registry + void shutdown(); + + std::recursive_mutex &tp_mutex(); + + void set_automatic_registration(bool automatic_registration); + + // set levels for all existing/future loggers. global_level can be null if should not set. + void set_levels(log_levels levels, level::level_enum *global_level); + + static registry &instance(); + + void apply_logger_env_levels(std::shared_ptr new_logger); + +private: + registry(); + ~registry(); + + void throw_if_exists_(const std::string &logger_name); + void register_logger_(std::shared_ptr new_logger); + void register_or_replace_(std::shared_ptr new_logger); + bool set_level_from_cfg_(logger *logger); + std::mutex logger_map_mutex_, flusher_mutex_; + std::recursive_mutex tp_mutex_; + std::unordered_map> loggers_; + log_levels log_levels_; + std::unique_ptr formatter_; + spdlog::level::level_enum global_log_level_ = level::info; + level::level_enum flush_level_ = level::off; + err_handler err_handler_; + std::shared_ptr tp_; + std::unique_ptr periodic_flusher_; + std::shared_ptr default_logger_; + bool automatic_registration_ = true; + size_t backtrace_n_messages_ = 0; +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "registry-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/synchronous_factory.h b/vendor/opensource/log_lib/spdlog/details/synchronous_factory.h new file mode 100755 index 0000000000000000000000000000000000000000..4bd5a51c86831e1808407c8cd5a34db36e95038c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/synchronous_factory.h @@ -0,0 +1,22 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "registry.h" + +namespace spdlog { + +// Default logger factory- creates synchronous loggers +class logger; + +struct synchronous_factory { + template + static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { + auto sink = std::make_shared(std::forward(args)...); + auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); + details::registry::instance().initialize_logger(new_logger); + return new_logger; + } +}; +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/tcp_client-windows.h b/vendor/opensource/log_lib/spdlog/details/tcp_client-windows.h new file mode 100755 index 0000000000000000000000000000000000000000..bf8f7b8791b273d542ab10af348ff3b830ae93c0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/tcp_client-windows.h @@ -0,0 +1,135 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#define WIN32_LEAN_AND_MEAN +// tcp client helper +#include +#include + +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Mswsock.lib") +#pragma comment(lib, "AdvApi32.lib") + +namespace spdlog { +namespace details { +class tcp_client { + SOCKET socket_ = INVALID_SOCKET; + + static void init_winsock_() { + WSADATA wsaData; + auto rv = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rv != 0) { + throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); + } + } + + static void throw_winsock_error_(const std::string &msg, int last_error) { + char buf[512]; + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, + (sizeof(buf) / sizeof(char)), NULL); + + throw_spdlog_ex(fmt_lib::format("tcp_sink - {}: {}", msg, buf)); + } + +public: + tcp_client() { init_winsock_(); } + + ~tcp_client() { + close(); + ::WSACleanup(); + } + + bool is_connected() const { return socket_ != INVALID_SOCKET; } + + void close() { + ::closesocket(socket_); + socket_ = INVALID_SOCKET; + } + + SOCKET fd() const { return socket_; } + + // try to connect or throw on failure + void connect(const std::string &host, int port) { + if (is_connected()) { + close(); + } + struct addrinfo hints {}; + ZeroMemory(&hints, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on + hints.ai_socktype = SOCK_STREAM; // TCP + hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value + hints.ai_protocol = 0; + + auto port_str = std::to_string(port); + struct addrinfo *addrinfo_result; + auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result); + int last_error = 0; + if (rv != 0) { + last_error = ::WSAGetLastError(); + WSACleanup(); + throw_winsock_error_("getaddrinfo failed", last_error); + } + + // Try each address until we successfully connect(2). + + for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next) { + socket_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (socket_ == INVALID_SOCKET) { + last_error = ::WSAGetLastError(); + WSACleanup(); + continue; + } + if (::connect(socket_, rp->ai_addr, (int)rp->ai_addrlen) == 0) { + break; + } else { + last_error = ::WSAGetLastError(); + close(); + } + } + ::freeaddrinfo(addrinfo_result); + if (socket_ == INVALID_SOCKET) { + WSACleanup(); + throw_winsock_error_("connect failed", last_error); + } + + // set TCP_NODELAY + int enable_flag = 1; + ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); + } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + size_t bytes_sent = 0; + while (bytes_sent < n_bytes) { + const int send_flags = 0; + auto write_result = + ::send(socket_, data + bytes_sent, (int)(n_bytes - bytes_sent), send_flags); + if (write_result == SOCKET_ERROR) { + int last_error = ::WSAGetLastError(); + close(); + throw_winsock_error_("send failed", last_error); + } + + if (write_result == 0) // (probably should not happen but in any case..) + { + break; + } + bytes_sent += static_cast(write_result); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/tcp_client.h b/vendor/opensource/log_lib/spdlog/details/tcp_client.h new file mode 100755 index 0000000000000000000000000000000000000000..9d3c40d525e26d52204115d5dcea52559664edd8 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/tcp_client.h @@ -0,0 +1,127 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef _WIN32 + #error include tcp_client-windows.h instead +#endif + +// tcp client helper +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace spdlog { +namespace details { +class tcp_client { + int socket_ = -1; + +public: + bool is_connected() const { return socket_ != -1; } + + void close() { + if (is_connected()) { + ::close(socket_); + socket_ = -1; + } + } + + int fd() const { return socket_; } + + ~tcp_client() { close(); } + + // try to connect or throw on failure + void connect(const std::string &host, int port) { + close(); + struct addrinfo hints {}; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on + hints.ai_socktype = SOCK_STREAM; // TCP + hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value + hints.ai_protocol = 0; + + auto port_str = std::to_string(port); + struct addrinfo *addrinfo_result; + auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result); + if (rv != 0) { + throw_spdlog_ex(fmt_lib::format("::getaddrinfo failed: {}", gai_strerror(rv))); + } + + // Try each address until we successfully connect(2). + int last_errno = 0; + for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next) { +#if defined(SOCK_CLOEXEC) + const int flags = SOCK_CLOEXEC; +#else + const int flags = 0; +#endif + socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol); + if (socket_ == -1) { + last_errno = errno; + continue; + } + rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen); + if (rv == 0) { + break; + } + last_errno = errno; + ::close(socket_); + socket_ = -1; + } + ::freeaddrinfo(addrinfo_result); + if (socket_ == -1) { + throw_spdlog_ex("::connect failed", last_errno); + } + + // set TCP_NODELAY + int enable_flag = 1; + ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); + + // prevent sigpipe on systems where MSG_NOSIGNAL is not available +#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) + ::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); +#endif + +#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) + #error "tcp_sink would raise SIGPIPE since neither SO_NOSIGPIPE nor MSG_NOSIGNAL are available" +#endif + } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + size_t bytes_sent = 0; + while (bytes_sent < n_bytes) { +#if defined(MSG_NOSIGNAL) + const int send_flags = MSG_NOSIGNAL; +#else + const int send_flags = 0; +#endif + auto write_result = + ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags); + if (write_result < 0) { + close(); + throw_spdlog_ex("write(2) failed", errno); + } + + if (write_result == 0) // (probably should not happen but in any case..) + { + break; + } + bytes_sent += static_cast(write_result); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/thread_pool-inl.h b/vendor/opensource/log_lib/spdlog/details/thread_pool-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..68b55369f071dd51721d02ae0ae13da77c240e61 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/thread_pool-inl.h @@ -0,0 +1,126 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start, + std::function on_thread_stop) + : q_(q_max_items) { + if (threads_n == 0 || threads_n > 1000) { + throw_spdlog_ex( + "spdlog::thread_pool(): invalid threads_n param (valid " + "range is 1-1000)"); + } + for (size_t i = 0; i < threads_n; i++) { + threads_.emplace_back([this, on_thread_start, on_thread_stop] { + on_thread_start(); + this->thread_pool::worker_loop_(); + on_thread_stop(); + }); + } +} + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start) + : thread_pool(q_max_items, threads_n, on_thread_start, [] {}) {} + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) + : thread_pool(q_max_items, threads_n, [] {}, [] {}) {} + +// message all threads to terminate gracefully join them +SPDLOG_INLINE thread_pool::~thread_pool() { + SPDLOG_TRY { + for (size_t i = 0; i < threads_.size(); i++) { + post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); + } + + for (auto &t : threads_) { + t.join(); + } + } + SPDLOG_CATCH_STD +} + +void SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, + const details::log_msg &msg, + async_overflow_policy overflow_policy) { + async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); + post_async_msg_(std::move(async_m), overflow_policy); +} + +void SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, + async_overflow_policy overflow_policy) { + post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); +} + +size_t SPDLOG_INLINE thread_pool::overrun_counter() { return q_.overrun_counter(); } + +void SPDLOG_INLINE thread_pool::reset_overrun_counter() { q_.reset_overrun_counter(); } + +size_t SPDLOG_INLINE thread_pool::discard_counter() { return q_.discard_counter(); } + +void SPDLOG_INLINE thread_pool::reset_discard_counter() { q_.reset_discard_counter(); } + +size_t SPDLOG_INLINE thread_pool::queue_size() { return q_.size(); } + +void SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, + async_overflow_policy overflow_policy) { + if (overflow_policy == async_overflow_policy::block) { + q_.enqueue(std::move(new_msg)); + } else if (overflow_policy == async_overflow_policy::overrun_oldest) { + q_.enqueue_nowait(std::move(new_msg)); + } else { + assert(overflow_policy == async_overflow_policy::discard_new); + q_.enqueue_if_have_room(std::move(new_msg)); + } +} + +void SPDLOG_INLINE thread_pool::worker_loop_() { + while (process_next_msg_()) { + } +} + +// process next message in the queue +// return true if this thread should still be active (while no terminate msg +// was received) +bool SPDLOG_INLINE thread_pool::process_next_msg_() { + async_msg incoming_async_msg; + q_.dequeue(incoming_async_msg); + + switch (incoming_async_msg.msg_type) { + case async_msg_type::log: { + incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); + return true; + } + case async_msg_type::flush: { + incoming_async_msg.worker_ptr->backend_flush_(); + return true; + } + + case async_msg_type::terminate: { + return false; + } + + default: { + assert(false); + } + } + + return true; +} + +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/thread_pool.h b/vendor/opensource/log_lib/spdlog/details/thread_pool.h new file mode 100755 index 0000000000000000000000000000000000000000..f22b0782103d8185577e72725c704258095b847e --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/thread_pool.h @@ -0,0 +1,117 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +class async_logger; + +namespace details { + +using async_logger_ptr = std::shared_ptr; + +enum class async_msg_type { log, flush, terminate }; + +// Async msg to move to/from the queue +// Movable only. should never be copied +struct async_msg : log_msg_buffer { + async_msg_type msg_type{async_msg_type::log}; + async_logger_ptr worker_ptr; + + async_msg() = default; + ~async_msg() = default; + + // should only be moved in or out of the queue.. + async_msg(const async_msg &) = delete; + +// support for vs2013 move +#if defined(_MSC_VER) && _MSC_VER <= 1800 + async_msg(async_msg &&other) + : log_msg_buffer(std::move(other)), + msg_type(other.msg_type), + worker_ptr(std::move(other.worker_ptr)) {} + + async_msg &operator=(async_msg &&other) { + *static_cast(this) = std::move(other); + msg_type = other.msg_type; + worker_ptr = std::move(other.worker_ptr); + return *this; + } +#else // (_MSC_VER) && _MSC_VER <= 1800 + async_msg(async_msg &&) = default; + async_msg &operator=(async_msg &&) = default; +#endif + + // construct from log_msg with given type + async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m) + : log_msg_buffer{m}, + msg_type{the_type}, + worker_ptr{std::move(worker)} {} + + async_msg(async_logger_ptr &&worker, async_msg_type the_type) + : log_msg_buffer{}, + msg_type{the_type}, + worker_ptr{std::move(worker)} {} + + explicit async_msg(async_msg_type the_type) + : async_msg{nullptr, the_type} {} +}; + +class SPDLOG_API thread_pool { +public: + using item_type = async_msg; + using q_type = details::mpmc_blocking_queue; + + thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start, + std::function on_thread_stop); + thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start); + thread_pool(size_t q_max_items, size_t threads_n); + + // message all threads to terminate gracefully and join them + ~thread_pool(); + + thread_pool(const thread_pool &) = delete; + thread_pool &operator=(thread_pool &&) = delete; + + void post_log(async_logger_ptr &&worker_ptr, + const details::log_msg &msg, + async_overflow_policy overflow_policy); + void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); + size_t overrun_counter(); + void reset_overrun_counter(); + size_t discard_counter(); + void reset_discard_counter(); + size_t queue_size(); + +private: + q_type q_; + + std::vector threads_; + + void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy); + void worker_loop_(); + + // process next message in the queue + // return true if this thread should still be active (while no terminate msg + // was received) + bool process_next_msg_(); +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "thread_pool-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/details/udp_client-windows.h b/vendor/opensource/log_lib/spdlog/details/udp_client-windows.h new file mode 100755 index 0000000000000000000000000000000000000000..8b7c22324e074322a0e7ba307c358fa78e8e2fb5 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/udp_client-windows.h @@ -0,0 +1,98 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over winsock udp client socket. +// Will throw on construction if socket creation failed. + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) + #pragma comment(lib, "Ws2_32.lib") + #pragma comment(lib, "Mswsock.lib") + #pragma comment(lib, "AdvApi32.lib") +#endif + +namespace spdlog { +namespace details { +class udp_client { + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + SOCKET socket_ = INVALID_SOCKET; + sockaddr_in addr_ = {}; + + static void init_winsock_() { + WSADATA wsaData; + auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rv != 0) { + throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); + } + } + + static void throw_winsock_error_(const std::string &msg, int last_error) { + char buf[512]; + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, + (sizeof(buf) / sizeof(char)), NULL); + + throw_spdlog_ex(fmt_lib::format("udp_sink - {}: {}", msg, buf)); + } + + void cleanup_() { + if (socket_ != INVALID_SOCKET) { + ::closesocket(socket_); + } + socket_ = INVALID_SOCKET; + ::WSACleanup(); + } + +public: + udp_client(const std::string &host, uint16_t port) { + init_winsock_(); + + addr_.sin_family = PF_INET; + addr_.sin_port = htons(port); + addr_.sin_addr.s_addr = INADDR_ANY; + if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1) { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Invalid address!", last_error); + } + + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ == INVALID_SOCKET) { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Create Socket failed", last_error); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, + reinterpret_cast(&option_value), sizeof(option_value)) < 0) { + int last_error = ::WSAGetLastError(); + cleanup_(); + throw_winsock_error_("error: setsockopt(SO_SNDBUF) Failed!", last_error); + } + } + + ~udp_client() { cleanup_(); } + + SOCKET fd() const { return socket_; } + + void send(const char *data, size_t n_bytes) { + socklen_t tolen = sizeof(struct sockaddr); + if (::sendto(socket_, data, static_cast(n_bytes), 0, (struct sockaddr *)&addr_, + tolen) == -1) { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/udp_client.h b/vendor/opensource/log_lib/spdlog/details/udp_client.h new file mode 100755 index 0000000000000000000000000000000000000000..95826f5d91d5792173af512c1f5220a6bd4e42c1 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/udp_client.h @@ -0,0 +1,81 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over unix udp client socket. +// Will throw on construction if the socket creation failed. + +#ifdef _WIN32 + #error "include udp_client-windows.h instead" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spdlog { +namespace details { + +class udp_client { + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + int socket_ = -1; + struct sockaddr_in sockAddr_; + + void cleanup_() { + if (socket_ != -1) { + ::close(socket_); + socket_ = -1; + } + } + +public: + udp_client(const std::string &host, uint16_t port) { + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ < 0) { + throw_spdlog_ex("error: Create Socket Failed!"); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, + reinterpret_cast(&option_value), sizeof(option_value)) < 0) { + cleanup_(); + throw_spdlog_ex("error: setsockopt(SO_SNDBUF) Failed!"); + } + + sockAddr_.sin_family = AF_INET; + sockAddr_.sin_port = htons(port); + + if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0) { + cleanup_(); + throw_spdlog_ex("error: Invalid address!"); + } + + ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero)); + } + + ~udp_client() { cleanup_(); } + + int fd() const { return socket_; } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + ssize_t toslen = 0; + socklen_t tolen = sizeof(struct sockaddr); + if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == + -1) { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/details/windows_include.h b/vendor/opensource/log_lib/spdlog/details/windows_include.h new file mode 100755 index 0000000000000000000000000000000000000000..bbab59b1c7645fdcc2a2c89b7b95e930df932fea --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/details/windows_include.h @@ -0,0 +1,11 @@ +#pragma once + +#ifndef NOMINMAX + #define NOMINMAX // prevent windows redefining min/max +#endif + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif + +#include diff --git a/vendor/opensource/log_lib/spdlog/fmt/bin_to_hex.h b/vendor/opensource/log_lib/spdlog/fmt/bin_to_hex.h new file mode 100755 index 0000000000000000000000000000000000000000..6ed68e427fa528cc875bb876c44def3279f161bd --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bin_to_hex.h @@ -0,0 +1,224 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include +#include + +#if defined(__has_include) + #if __has_include() + #include + #endif +#endif + +#if __cpp_lib_span >= 202002L + #include +#endif + +// +// Support for logging binary data as hex +// format flags, any combination of the following: +// {:X} - print in uppercase. +// {:s} - don't separate each byte with space. +// {:p} - don't print the position on each line start. +// {:n} - don't split the output to lines. +// {:a} - show ASCII if :n is not set + +// +// Examples: +// +// std::vector v(200, 0x0b); +// logger->info("Some buffer {}", spdlog::to_hex(v)); +// char buf[128]; +// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf))); +// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf), 16)); + +namespace spdlog { +namespace details { + +template +class dump_info { +public: + dump_info(It range_begin, It range_end, size_t size_per_line) + : begin_(range_begin), + end_(range_end), + size_per_line_(size_per_line) {} + + // do not use begin() and end() to avoid collision with fmt/ranges + It get_begin() const { return begin_; } + It get_end() const { return end_; } + size_t size_per_line() const { return size_per_line_; } + +private: + It begin_, end_; + size_t size_per_line_; +}; +} // namespace details + +// create a dump_info that wraps the given container +template +inline details::dump_info to_hex(const Container &container, + size_t size_per_line = 32) { + static_assert(sizeof(typename Container::value_type) == 1, + "sizeof(Container::value_type) != 1"); + using Iter = typename Container::const_iterator; + return details::dump_info(std::begin(container), std::end(container), size_per_line); +} + +#if __cpp_lib_span >= 202002L + +template +inline details::dump_info::iterator> to_hex( + const std::span &container, size_t size_per_line = 32) { + using Container = std::span; + static_assert(sizeof(typename Container::value_type) == 1, + "sizeof(Container::value_type) != 1"); + using Iter = typename Container::iterator; + return details::dump_info(std::begin(container), std::end(container), size_per_line); +} + +#endif + +// create dump_info from ranges +template +inline details::dump_info to_hex(const It range_begin, + const It range_end, + size_t size_per_line = 32) { + return details::dump_info(range_begin, range_end, size_per_line); +} + +} // namespace spdlog + +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + +template +struct formatter, char> { + char delimiter = ' '; + bool put_newlines = true; + bool put_delimiters = true; + bool use_uppercase = false; + bool put_positions = true; // position on start of each line + bool show_ascii = false; + + // parse the format string flags + template + SPDLOG_CONSTEXPR_FUNC auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + while (it != ctx.end() && *it != '}') { + switch (*it) { + case 'X': + use_uppercase = true; + break; + case 's': + put_delimiters = false; + break; + case 'p': + put_positions = false; + break; + case 'n': + put_newlines = false; + show_ascii = false; + break; + case 'a': + if (put_newlines) { + show_ascii = true; + } + break; + } + + ++it; + } + return it; + } + + // format the given bytes range as hex + template + auto format(const spdlog::details::dump_info &the_range, + FormatContext &ctx) const -> decltype(ctx.out()) { + SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF"; + SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef"; + const char *hex_chars = use_uppercase ? hex_upper : hex_lower; + +#if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION < 60000 + auto inserter = ctx.begin(); +#else + auto inserter = ctx.out(); +#endif + + int size_per_line = static_cast(the_range.size_per_line()); + auto start_of_line = the_range.get_begin(); + for (auto i = the_range.get_begin(); i != the_range.get_end(); i++) { + auto ch = static_cast(*i); + + if (put_newlines && + (i == the_range.get_begin() || i - start_of_line >= size_per_line)) { + if (show_ascii && i != the_range.get_begin()) { + *inserter++ = delimiter; + *inserter++ = delimiter; + for (auto j = start_of_line; j < i; j++) { + auto pc = static_cast(*j); + *inserter++ = std::isprint(pc) ? static_cast(*j) : '.'; + } + } + + put_newline(inserter, static_cast(i - the_range.get_begin())); + + // put first byte without delimiter in front of it + *inserter++ = hex_chars[(ch >> 4) & 0x0f]; + *inserter++ = hex_chars[ch & 0x0f]; + start_of_line = i; + continue; + } + + if (put_delimiters && i != the_range.get_begin()) { + *inserter++ = delimiter; + } + + *inserter++ = hex_chars[(ch >> 4) & 0x0f]; + *inserter++ = hex_chars[ch & 0x0f]; + } + if (show_ascii) // add ascii to last line + { + if (the_range.get_end() - the_range.get_begin() > size_per_line) { + auto blank_num = size_per_line - (the_range.get_end() - start_of_line); + while (blank_num-- > 0) { + *inserter++ = delimiter; + *inserter++ = delimiter; + if (put_delimiters) { + *inserter++ = delimiter; + } + } + } + *inserter++ = delimiter; + *inserter++ = delimiter; + for (auto j = start_of_line; j != the_range.get_end(); j++) { + auto pc = static_cast(*j); + *inserter++ = std::isprint(pc) ? static_cast(*j) : '.'; + } + } + return inserter; + } + + // put newline(and position header) + template + void put_newline(It inserter, std::size_t pos) const { +#ifdef _WIN32 + *inserter++ = '\r'; +#endif + *inserter++ = '\n'; + + if (put_positions) { + spdlog::fmt_lib::format_to(inserter, SPDLOG_FMT_STRING("{:04X}: "), pos); + } + } +}; +} // namespace std diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/args.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/args.h new file mode 100755 index 0000000000000000000000000000000000000000..3ff47880748fb1e03e61ad722523a9611dcf27d8 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/args.h @@ -0,0 +1,220 @@ +// Formatting library for C++ - dynamic argument lists +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_ARGS_H_ +#define FMT_ARGS_H_ + +#ifndef FMT_MODULE +# include // std::reference_wrapper +# include // std::unique_ptr +# include +#endif + +#include "format.h" // std_string_view + +FMT_BEGIN_NAMESPACE +namespace detail { + +template struct is_reference_wrapper : std::false_type {}; +template +struct is_reference_wrapper> : std::true_type {}; + +template auto unwrap(const T& v) -> const T& { return v; } +template +auto unwrap(const std::reference_wrapper& v) -> const T& { + return static_cast(v); +} + +// node is defined outside dynamic_arg_list to workaround a C2504 bug in MSVC +// 2022 (v17.10.0). +// +// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for +// templates it doesn't complain about inability to deduce single translation +// unit for placing vtable. So node is made a fake template. +template struct node { + virtual ~node() = default; + std::unique_ptr> next; +}; + +class dynamic_arg_list { + template struct typed_node : node<> { + T value; + + template + FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} + + template + FMT_CONSTEXPR typed_node(const basic_string_view& arg) + : value(arg.data(), arg.size()) {} + }; + + std::unique_ptr> head_; + + public: + template auto push(const Arg& arg) -> const T& { + auto new_node = std::unique_ptr>(new typed_node(arg)); + auto& value = new_node->value; + new_node->next = std::move(head_); + head_ = std::move(new_node); + return value; + } +}; +} // namespace detail + +/** + * A dynamic list of formatting arguments with storage. + * + * It can be implicitly converted into `fmt::basic_format_args` for passing + * into type-erased formatting functions such as `fmt::vformat`. + */ +template class dynamic_format_arg_store { + private: + using char_type = typename Context::char_type; + + template struct need_copy { + static constexpr detail::type mapped_type = + detail::mapped_type_constant::value; + + enum { + value = !(detail::is_reference_wrapper::value || + std::is_same>::value || + std::is_same>::value || + (mapped_type != detail::type::cstring_type && + mapped_type != detail::type::string_type && + mapped_type != detail::type::custom_type)) + }; + }; + + template + using stored_t = conditional_t< + std::is_convertible>::value && + !detail::is_reference_wrapper::value, + std::basic_string, T>; + + // Storage of basic_format_arg must be contiguous. + std::vector> data_; + std::vector> named_info_; + + // Storage of arguments not fitting into basic_format_arg must grow + // without relocation because items in data_ refer to it. + detail::dynamic_arg_list dynamic_args_; + + friend class basic_format_args; + + auto data() const -> const basic_format_arg* { + return named_info_.empty() ? data_.data() : data_.data() + 1; + } + + template void emplace_arg(const T& arg) { + data_.emplace_back(arg); + } + + template + void emplace_arg(const detail::named_arg& arg) { + if (named_info_.empty()) + data_.insert(data_.begin(), basic_format_arg(nullptr, 0)); + data_.emplace_back(detail::unwrap(arg.value)); + auto pop_one = [](std::vector>* data) { + data->pop_back(); + }; + std::unique_ptr>, decltype(pop_one)> + guard{&data_, pop_one}; + named_info_.push_back({arg.name, static_cast(data_.size() - 2u)}); + data_[0] = {named_info_.data(), named_info_.size()}; + guard.release(); + } + + public: + constexpr dynamic_format_arg_store() = default; + + operator basic_format_args() const { + return basic_format_args(data(), static_cast(data_.size()), + !named_info_.empty()); + } + + /** + * Adds an argument into the dynamic store for later passing to a formatting + * function. + * + * Note that custom types and string types (but not string views) are copied + * into the store dynamically allocating memory if necessary. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * store.push_back(42); + * store.push_back("abc"); + * store.push_back(1.5f); + * std::string result = fmt::vformat("{} and {} and {}", store); + */ + template void push_back(const T& arg) { + if (detail::const_check(need_copy::value)) + emplace_arg(dynamic_args_.push>(arg)); + else + emplace_arg(detail::unwrap(arg)); + } + + /** + * Adds a reference to the argument into the dynamic store for later passing + * to a formatting function. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * char band[] = "Rolling Stones"; + * store.push_back(std::cref(band)); + * band[9] = 'c'; // Changing str affects the output. + * std::string result = fmt::vformat("{}", store); + * // result == "Rolling Scones" + */ + template void push_back(std::reference_wrapper arg) { + static_assert( + need_copy::value, + "objects of built-in types and string views are always copied"); + emplace_arg(arg.get()); + } + + /** + * Adds named argument into the dynamic store for later passing to a + * formatting function. `std::reference_wrapper` is supported to avoid + * copying of the argument. The name is always copied into the store. + */ + template + void push_back(const detail::named_arg& arg) { + const char_type* arg_name = + dynamic_args_.push>(arg.name).c_str(); + if (detail::const_check(need_copy::value)) { + emplace_arg( + fmt::arg(arg_name, dynamic_args_.push>(arg.value))); + } else { + emplace_arg(fmt::arg(arg_name, arg.value)); + } + } + + /// Erase all elements from the store. + void clear() { + data_.clear(); + named_info_.clear(); + dynamic_args_ = {}; + } + + /// Reserves space to store at least `new_cap` arguments including + /// `new_cap_named` named arguments. + void reserve(size_t new_cap, size_t new_cap_named) { + FMT_ASSERT(new_cap >= new_cap_named, + "set of arguments includes set of named arguments"); + data_.reserve(new_cap); + named_info_.reserve(new_cap_named); + } + + /// Returns the number of elements in the store. + size_t size() const noexcept { return data_.size(); } +}; + +FMT_END_NAMESPACE + +#endif // FMT_ARGS_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/base.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/base.h new file mode 100755 index 0000000000000000000000000000000000000000..e0e8748eae620416e2f87fa7050a80c84175a312 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/base.h @@ -0,0 +1,2989 @@ +// Formatting library for C++ - the base API for char/UTF-8 +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_BASE_H_ +#define FMT_BASE_H_ + +#if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE) +# define FMT_MODULE +#endif + +#ifndef FMT_MODULE +# include // CHAR_BIT +# include // FILE +# include // memcmp + +# include // std::enable_if +#endif + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 110200 + +// Detect compiler versions. +#if defined(__clang__) && !defined(__ibmxl__) +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif +#if defined(__ICL) +# define FMT_ICC_VERSION __ICL +#elif defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif +#if defined(_MSC_VER) +# define FMT_MSC_VERSION _MSC_VER +#else +# define FMT_MSC_VERSION 0 +#endif + +// Detect standard library versions. +#ifdef _GLIBCXX_RELEASE +# define FMT_GLIBCXX_RELEASE _GLIBCXX_RELEASE +#else +# define FMT_GLIBCXX_RELEASE 0 +#endif +#ifdef _LIBCPP_VERSION +# define FMT_LIBCPP_VERSION _LIBCPP_VERSION +#else +# define FMT_LIBCPP_VERSION 0 +#endif + +#ifdef _MSVC_LANG +# define FMT_CPLUSPLUS _MSVC_LANG +#else +# define FMT_CPLUSPLUS __cplusplus +#endif + +// Detect __has_*. +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif +#ifdef __has_include +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif +#ifdef __has_builtin +# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define FMT_HAS_BUILTIN(x) 0 +#endif +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +// Detect C++14 relaxed constexpr. +#ifdef FMT_USE_CONSTEXPR +// Use the provided definition. +#elif FMT_GCC_VERSION >= 702 && FMT_CPLUSPLUS >= 201402L +// GCC only allows constexpr member functions in non-literal types since 7.2: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66297. +# define FMT_USE_CONSTEXPR 1 +#elif FMT_ICC_VERSION +# define FMT_USE_CONSTEXPR 0 // https://github.com/fmtlib/fmt/issues/1628 +#elif FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 +# define FMT_USE_CONSTEXPR 1 +#else +# define FMT_USE_CONSTEXPR 0 +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +#else +# define FMT_CONSTEXPR +#endif + +// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. +#if !defined(__cpp_lib_is_constant_evaluated) +# define FMT_USE_CONSTEVAL 0 +#elif FMT_CPLUSPLUS < 201709L +# define FMT_USE_CONSTEVAL 0 +#elif FMT_GLIBCXX_RELEASE && FMT_GLIBCXX_RELEASE < 10 +# define FMT_USE_CONSTEVAL 0 +#elif FMT_LIBCPP_VERSION && FMT_LIBCPP_VERSION < 10000 +# define FMT_USE_CONSTEVAL 0 +#elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L +# define FMT_USE_CONSTEVAL 0 // consteval is broken in Apple clang < 14. +#elif FMT_MSC_VERSION && FMT_MSC_VERSION < 1929 +# define FMT_USE_CONSTEVAL 0 // consteval is broken in MSVC VS2019 < 16.10. +#elif defined(__cpp_consteval) +# define FMT_USE_CONSTEVAL 1 +#elif FMT_GCC_VERSION >= 1002 || FMT_CLANG_VERSION >= 1101 +# define FMT_USE_CONSTEVAL 1 +#else +# define FMT_USE_CONSTEVAL 0 +#endif +#if FMT_USE_CONSTEVAL +# define FMT_CONSTEVAL consteval +# define FMT_CONSTEXPR20 constexpr +#else +# define FMT_CONSTEVAL +# define FMT_CONSTEXPR20 +#endif + +// Check if exceptions are disabled. +#ifdef FMT_USE_EXCEPTIONS +// Use the provided definition. +#elif defined(__GNUC__) && !defined(__EXCEPTIONS) +# define FMT_USE_EXCEPTIONS 0 +#elif defined(__clang__) && !defined(__cpp_exceptions) +# define FMT_USE_EXCEPTIONS 0 +#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS +# define FMT_USE_EXCEPTIONS 0 +#else +# define FMT_USE_EXCEPTIONS 1 +#endif +#if FMT_USE_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifdef FMT_NO_UNIQUE_ADDRESS +// Use the provided definition. +#elif FMT_CPLUSPLUS < 202002L +// Not supported. +#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address) +# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] +// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485). +#elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION +# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#endif +#ifndef FMT_NO_UNIQUE_ADDRESS +# define FMT_NO_UNIQUE_ADDRESS +#endif + +#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough) +# define FMT_FALLTHROUGH [[fallthrough]] +#elif defined(__clang__) +# define FMT_FALLTHROUGH [[clang::fallthrough]] +#elif FMT_GCC_VERSION >= 700 && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) +# define FMT_FALLTHROUGH [[gnu::fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +// Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings. +#if FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && !defined(__NVCC__) +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#ifdef FMT_NODISCARD +// Use the provided definition. +#elif FMT_HAS_CPP17_ATTRIBUTE(nodiscard) +# define FMT_NODISCARD [[nodiscard]] +#else +# define FMT_NODISCARD +#endif + +#ifdef FMT_DEPRECATED +// Use the provided definition. +#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated) +# define FMT_DEPRECATED [[deprecated]] +#else +# define FMT_DEPRECATED /* deprecated */ +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_VISIBILITY(value) __attribute__((visibility(value))) +#else +# define FMT_VISIBILITY(value) +#endif + +// Detect pragmas. +#define FMT_PRAGMA_IMPL(x) _Pragma(#x) +#if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER) +// Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884 +// and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582. +# define FMT_PRAGMA_GCC(x) FMT_PRAGMA_IMPL(GCC x) +#else +# define FMT_PRAGMA_GCC(x) +#endif +#if FMT_CLANG_VERSION +# define FMT_PRAGMA_CLANG(x) FMT_PRAGMA_IMPL(clang x) +#else +# define FMT_PRAGMA_CLANG(x) +#endif +#if FMT_MSC_VERSION +# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) +#else +# define FMT_MSC_WARNING(...) +#endif + +// Enable minimal optimizations for more compact code in debug mode. +FMT_PRAGMA_GCC(push_options) +#if !defined(__OPTIMIZE__) && !defined(__CUDACC__) && !defined(FMT_MODULE) +FMT_PRAGMA_GCC(optimize("Og")) +# define FMT_GCC_OPTIMIZED +#endif +FMT_PRAGMA_CLANG(diagnostic push) + +#ifdef FMT_ALWAYS_INLINE +// Use the provided definition. +#elif FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_ALWAYS_INLINE inline __attribute__((always_inline)) +#else +# define FMT_ALWAYS_INLINE inline +#endif +// A version of FMT_ALWAYS_INLINE to prevent code bloat in debug mode. +#if defined(NDEBUG) || defined(FMT_GCC_OPTIMIZED) +# define FMT_INLINE FMT_ALWAYS_INLINE +#else +# define FMT_INLINE inline +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + inline namespace v11 { +# define FMT_END_NAMESPACE \ + } \ + } +#endif + +#ifndef FMT_EXPORT +# define FMT_EXPORT +# define FMT_BEGIN_EXPORT +# define FMT_END_EXPORT +#endif + +#ifdef _WIN32 +# define FMT_WIN32 1 +#else +# define FMT_WIN32 0 +#endif + +#if !defined(FMT_HEADER_ONLY) && FMT_WIN32 +# if defined(FMT_LIB_EXPORT) +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# endif +#elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) +# define FMT_API FMT_VISIBILITY("default") +#endif +#ifndef FMT_API +# define FMT_API +#endif + +#ifndef FMT_OPTIMIZE_SIZE +# define FMT_OPTIMIZE_SIZE 0 +#endif + +// FMT_BUILTIN_TYPE=0 may result in smaller library size at the cost of higher +// per-call binary size by passing built-in types through the extension API. +#ifndef FMT_BUILTIN_TYPES +# define FMT_BUILTIN_TYPES 1 +#endif + +#define FMT_APPLY_VARIADIC(expr) \ + using unused = int[]; \ + (void)unused { 0, (expr, 0)... } + +FMT_BEGIN_NAMESPACE + +// Implementations of enable_if_t and other metafunctions for older systems. +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; +template using bool_constant = std::integral_constant; +template +using remove_reference_t = typename std::remove_reference::type; +template +using remove_const_t = typename std::remove_const::type; +template +using remove_cvref_t = typename std::remove_cv>::type; +template +using make_unsigned_t = typename std::make_unsigned::type; +template +using underlying_t = typename std::underlying_type::type; +template using decay_t = typename std::decay::type; +using nullptr_t = decltype(nullptr); + +#if (FMT_GCC_VERSION && FMT_GCC_VERSION < 500) || FMT_MSC_VERSION +// A workaround for gcc 4.9 & MSVC v141 to make void_t work in a SFINAE context. +template struct void_t_impl { + using type = void; +}; +template using void_t = typename void_t_impl::type; +#else +template using void_t = void; +#endif + +struct monostate { + constexpr monostate() {} +}; + +// An enable_if helper to be used in template parameters which results in much +// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed +// to workaround a bug in MSVC 2019 (see #1140 and #1186). +#ifdef FMT_DOC +# define FMT_ENABLE_IF(...) +#else +# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0 +#endif + +template constexpr auto min_of(T a, T b) -> T { + return a < b ? a : b; +} +template constexpr auto max_of(T a, T b) -> T { + return a > b ? a : b; +} + +namespace detail { +// Suppresses "unused variable" warnings with the method described in +// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. +// (void)var does not work on many Intel compilers. +template FMT_CONSTEXPR void ignore_unused(const T&...) {} + +constexpr auto is_constant_evaluated(bool default_value = false) noexcept + -> bool { +// Workaround for incompatibility between clang 14 and libstdc++ consteval-based +// std::is_constant_evaluated: https://github.com/fmtlib/fmt/issues/3247. +#if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \ + (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500) + ignore_unused(default_value); + return __builtin_is_constant_evaluated(); +#elif defined(__cpp_lib_is_constant_evaluated) + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// Suppresses "conditional expression is constant" warnings. +template FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T { + return val; +} + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#if defined(FMT_ASSERT) +// Use the provided definition. +#elif defined(NDEBUG) +// FMT_ASSERT is not empty to avoid -Wempty-body. +# define FMT_ASSERT(condition, message) \ + fmt::detail::ignore_unused((condition), (message)) +#else +# define FMT_ASSERT(condition, message) \ + ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ + ? (void)0 \ + : fmt::detail::assert_fail(__FILE__, __LINE__, (message))) +#endif + +#ifdef FMT_USE_INT128 +// Use the provided definition. +#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \ + !(FMT_CLANG_VERSION && FMT_MSC_VERSION) +# define FMT_USE_INT128 1 +using int128_opt = __int128_t; // An optional native 128-bit integer. +using uint128_opt = __uint128_t; +inline auto map(int128_opt x) -> int128_opt { return x; } +inline auto map(uint128_opt x) -> uint128_opt { return x; } +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +enum class int128_opt {}; +enum class uint128_opt {}; +// Reduce template instantiations. +inline auto map(int128_opt) -> monostate { return {}; } +inline auto map(uint128_opt) -> monostate { return {}; } +#endif + +#ifndef FMT_USE_BITINT +# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500) +#endif + +#if FMT_USE_BITINT +FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") +template using bitint = _BitInt(N); +template using ubitint = unsigned _BitInt(N); +#else +template struct bitint {}; +template struct ubitint {}; +#endif // FMT_USE_BITINT + +// Casts a nonnegative integer to unsigned. +template +FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t { + FMT_ASSERT(std::is_unsigned::value || value >= 0, "negative value"); + return static_cast>(value); +} + +template +using unsigned_char = conditional_t; + +// A heuristic to detect std::string and std::[experimental::]string_view. +// It is mainly used to avoid dependency on <[experimental/]string_view>. +template +struct is_std_string_like : std::false_type {}; +template +struct is_std_string_like().find_first_of( + typename T::value_type(), 0))>> + : std::is_convertible().data()), + const typename T::value_type*> {}; + +// Check if the literal encoding is UTF-8. +enum { is_utf8_enabled = "\u00A7"[1] == '\xA7' }; +enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled }; + +#ifndef FMT_UNICODE +# define FMT_UNICODE 1 +#endif + +static_assert(!FMT_UNICODE || use_utf8, + "Unicode support requires compiling with /utf-8"); + +template constexpr const char* narrow(const T*) { return nullptr; } +constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; } + +template +FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) + -> int { + if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); + for (; n != 0; ++s1, ++s2, --n) { + if (*s1 < *s2) return -1; + if (*s1 > *s2) return 1; + } + return 0; +} + +namespace adl { +using namespace std; + +template +auto invoke_back_inserter() + -> decltype(back_inserter(std::declval())); +} // namespace adl + +template +struct is_back_insert_iterator : std::false_type {}; + +template +struct is_back_insert_iterator< + It, bool_constant()), + It>::value>> : std::true_type {}; + +// Extracts a reference to the container from *insert_iterator. +template +inline FMT_CONSTEXPR20 auto get_container(OutputIt it) -> + typename OutputIt::container_type& { + struct accessor : OutputIt { + FMT_CONSTEXPR20 accessor(OutputIt base) : OutputIt(base) {} + using OutputIt::container; + }; + return *accessor(it).container; +} +} // namespace detail + +// Parsing-related public API and forward declarations. +FMT_BEGIN_EXPORT + +/** + * An implementation of `std::basic_string_view` for pre-C++17. It provides a + * subset of the API. `fmt::basic_string_view` is used for format strings even + * if `std::basic_string_view` is available to prevent issues when a library is + * compiled with a different `-std` option than the client code (which is not + * recommended). + */ +template class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} + + /// Constructs a string view object from a C string and a size. + constexpr basic_string_view(const Char* s, size_t count) noexcept + : data_(s), size_(count) {} + + constexpr basic_string_view(nullptr_t) = delete; + + /// Constructs a string view object from a C string. +#if FMT_GCC_VERSION + FMT_ALWAYS_INLINE +#endif + FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) { +#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION + if (std::is_same::value && !detail::is_constant_evaluated()) { + size_ = __builtin_strlen(detail::narrow(s)); // strlen is not costexpr. + return; + } +#endif + size_t len = 0; + while (*s++) ++len; + size_ = len; + } + + /// Constructs a string view from a `std::basic_string` or a + /// `std::basic_string_view` object. + template ::value&& std::is_same< + typename S::value_type, Char>::value)> + FMT_CONSTEXPR basic_string_view(const S& s) noexcept + : data_(s.data()), size_(s.size()) {} + + /// Returns a pointer to the string data. + constexpr auto data() const noexcept -> const Char* { return data_; } + + /// Returns the string size. + constexpr auto size() const noexcept -> size_t { return size_; } + + constexpr auto begin() const noexcept -> iterator { return data_; } + constexpr auto end() const noexcept -> iterator { return data_ + size_; } + + constexpr auto operator[](size_t pos) const noexcept -> const Char& { + return data_[pos]; + } + + FMT_CONSTEXPR void remove_prefix(size_t n) noexcept { + data_ += n; + size_ -= n; + } + + FMT_CONSTEXPR auto starts_with(basic_string_view sv) const noexcept + -> bool { + return size_ >= sv.size_ && detail::compare(data_, sv.data_, sv.size_) == 0; + } + FMT_CONSTEXPR auto starts_with(Char c) const noexcept -> bool { + return size_ >= 1 && *data_ == c; + } + FMT_CONSTEXPR auto starts_with(const Char* s) const -> bool { + return starts_with(basic_string_view(s)); + } + + FMT_CONSTEXPR auto compare(basic_string_view other) const -> int { + int result = + detail::compare(data_, other.data_, min_of(size_, other.size_)); + if (result != 0) return result; + return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + } + + FMT_CONSTEXPR friend auto operator==(basic_string_view lhs, + basic_string_view rhs) -> bool { + return lhs.compare(rhs) == 0; + } + friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) != 0; + } + friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) < 0; + } + friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) <= 0; + } + friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) > 0; + } + friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) >= 0; + } +}; + +using string_view = basic_string_view; + +// DEPRECATED! Will be merged with is_char and moved to detail. +template struct is_xchar : std::false_type {}; +template <> struct is_xchar : std::true_type {}; +template <> struct is_xchar : std::true_type {}; +template <> struct is_xchar : std::true_type {}; +#ifdef __cpp_char8_t +template <> struct is_xchar : std::true_type {}; +#endif + +// Specifies if `T` is a character (code unit) type. +template struct is_char : is_xchar {}; +template <> struct is_char : std::true_type {}; + +template class basic_appender; +using appender = basic_appender; + +// Checks whether T is a container with contiguous storage. +template struct is_contiguous : std::false_type {}; + +class context; +template class generic_context; +template class parse_context; + +// Longer aliases for C++20 compatibility. +template using basic_format_parse_context = parse_context; +using format_parse_context = parse_context; +template +using basic_format_context = + conditional_t::value, context, + generic_context>; +using format_context = context; + +template +using buffered_context = + conditional_t::value, context, + generic_context, Char>>; + +template class basic_format_arg; +template class basic_format_args; + +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args; + +// A formatter for objects of type T. +template +struct formatter { + // A deleted default export_class indicates a disabled formatter. + formatter() = delete; +}; + +/// Reports a format error at compile time or, via a `format_error` exception, +/// at runtime. +// This function is intentionally not constexpr to give a compile-time error. +FMT_NORETURN FMT_API void report_error(const char* message); + +enum class presentation_type : unsigned char { + // Common specifiers: + none = 0, + debug = 1, // '?' + string = 2, // 's' (string, bool) + + // Integral, bool and character specifiers: + dec = 3, // 'd' + hex, // 'x' or 'X' + oct, // 'o' + bin, // 'b' or 'B' + chr, // 'c' + + // String and pointer specifiers: + pointer = 3, // 'p' + + // Floating-point specifiers: + exp = 1, // 'e' or 'E' (1 since there is no FP debug presentation) + fixed, // 'f' or 'F' + general, // 'g' or 'G' + hexfloat // 'a' or 'A' +}; + +enum class align { none, left, right, center, numeric }; +enum class sign { none, minus, plus, space }; +enum class arg_id_kind { none, index, name }; + +// Basic format specifiers for built-in and string types. +class basic_specs { + private: + // Data is arranged as follows: + // + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |type |align| w | p | s |u|#|L| f | unused | + // +-----+-----+---+---+---+-+-+-+-----+---------------------------+ + // + // w - dynamic width info + // p - dynamic precision info + // s - sign + // u - uppercase (e.g. 'X' for 'x') + // # - alternate form ('#') + // L - localized + // f - fill size + // + // Bitfields are not used because of compiler bugs such as gcc bug 61414. + enum : unsigned { + type_mask = 0x00007, + align_mask = 0x00038, + width_mask = 0x000C0, + precision_mask = 0x00300, + sign_mask = 0x00C00, + uppercase_mask = 0x01000, + alternate_mask = 0x02000, + localized_mask = 0x04000, + fill_size_mask = 0x38000, + + align_shift = 3, + width_shift = 6, + precision_shift = 8, + sign_shift = 10, + fill_size_shift = 15, + + max_fill_size = 4 + }; + + unsigned data_ = 1 << fill_size_shift; + static_assert(sizeof(basic_specs::data_) * CHAR_BIT >= 18, ""); + + // Character (code unit) type is erased to prevent template bloat. + char fill_data_[max_fill_size] = {' '}; + + FMT_CONSTEXPR void set_fill_size(size_t size) { + data_ = (data_ & ~fill_size_mask) | + (static_cast(size) << fill_size_shift); + } + + public: + constexpr auto type() const -> presentation_type { + return static_cast(data_ & type_mask); + } + FMT_CONSTEXPR void set_type(presentation_type t) { + data_ = (data_ & ~type_mask) | static_cast(t); + } + + constexpr auto align() const -> align { + return static_cast((data_ & align_mask) >> align_shift); + } + FMT_CONSTEXPR void set_align(fmt::align a) { + data_ = (data_ & ~align_mask) | (static_cast(a) << align_shift); + } + + constexpr auto dynamic_width() const -> arg_id_kind { + return static_cast((data_ & width_mask) >> width_shift); + } + FMT_CONSTEXPR void set_dynamic_width(arg_id_kind w) { + data_ = (data_ & ~width_mask) | (static_cast(w) << width_shift); + } + + FMT_CONSTEXPR auto dynamic_precision() const -> arg_id_kind { + return static_cast((data_ & precision_mask) >> + precision_shift); + } + FMT_CONSTEXPR void set_dynamic_precision(arg_id_kind p) { + data_ = (data_ & ~precision_mask) | + (static_cast(p) << precision_shift); + } + + constexpr bool dynamic() const { + return (data_ & (width_mask | precision_mask)) != 0; + } + + constexpr auto sign() const -> sign { + return static_cast((data_ & sign_mask) >> sign_shift); + } + FMT_CONSTEXPR void set_sign(fmt::sign s) { + data_ = (data_ & ~sign_mask) | (static_cast(s) << sign_shift); + } + + constexpr auto upper() const -> bool { return (data_ & uppercase_mask) != 0; } + FMT_CONSTEXPR void set_upper() { data_ |= uppercase_mask; } + + constexpr auto alt() const -> bool { return (data_ & alternate_mask) != 0; } + FMT_CONSTEXPR void set_alt() { data_ |= alternate_mask; } + FMT_CONSTEXPR void clear_alt() { data_ &= ~alternate_mask; } + + constexpr auto localized() const -> bool { + return (data_ & localized_mask) != 0; + } + FMT_CONSTEXPR void set_localized() { data_ |= localized_mask; } + + constexpr auto fill_size() const -> size_t { + return (data_ & fill_size_mask) >> fill_size_shift; + } + + template ::value)> + constexpr auto fill() const -> const Char* { + return fill_data_; + } + template ::value)> + constexpr auto fill() const -> const Char* { + return nullptr; + } + + template constexpr auto fill_unit() const -> Char { + using uchar = unsigned char; + return static_cast(static_cast(fill_data_[0]) | + (static_cast(fill_data_[1]) << 8) | + (static_cast(fill_data_[2]) << 16)); + } + + FMT_CONSTEXPR void set_fill(char c) { + fill_data_[0] = c; + set_fill_size(1); + } + + template + FMT_CONSTEXPR void set_fill(basic_string_view s) { + auto size = s.size(); + set_fill_size(size); + if (size == 1) { + unsigned uchar = static_cast>(s[0]); + fill_data_[0] = static_cast(uchar); + fill_data_[1] = static_cast(uchar >> 8); + fill_data_[2] = static_cast(uchar >> 16); + return; + } + FMT_ASSERT(size <= max_fill_size, "invalid fill"); + for (size_t i = 0; i < size; ++i) + fill_data_[i & 3] = static_cast(s[i]); + } + + FMT_CONSTEXPR void copy_fill_from(const basic_specs& specs) { + set_fill_size(specs.fill_size()); + for (size_t i = 0; i < max_fill_size; ++i) + fill_data_[i] = specs.fill_data_[i]; + } +}; + +// Format specifiers for built-in and string types. +struct format_specs : basic_specs { + int width; + int precision; + + constexpr format_specs() : width(0), precision(-1) {} +}; + +/** + * Parsing context consisting of a format string range being parsed and an + * argument counter for automatic indexing. + */ +template class parse_context { + private: + basic_string_view fmt_; + int next_arg_id_; + + enum { use_constexpr_cast = !FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200 }; + + FMT_CONSTEXPR void do_check_arg_id(int arg_id); + + public: + using char_type = Char; + using iterator = const Char*; + + constexpr explicit parse_context(basic_string_view fmt, + int next_arg_id = 0) + : fmt_(fmt), next_arg_id_(next_arg_id) {} + + /// Returns an iterator to the beginning of the format string range being + /// parsed. + constexpr auto begin() const noexcept -> iterator { return fmt_.begin(); } + + /// Returns an iterator past the end of the format string range being parsed. + constexpr auto end() const noexcept -> iterator { return fmt_.end(); } + + /// Advances the begin iterator to `it`. + FMT_CONSTEXPR void advance_to(iterator it) { + fmt_.remove_prefix(detail::to_unsigned(it - begin())); + } + + /// Reports an error if using the manual argument indexing; otherwise returns + /// the next argument index and switches to the automatic indexing. + FMT_CONSTEXPR auto next_arg_id() -> int { + if (next_arg_id_ < 0) { + report_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + int id = next_arg_id_++; + do_check_arg_id(id); + return id; + } + + /// Reports an error if using the automatic argument indexing; otherwise + /// switches to the manual indexing. + FMT_CONSTEXPR void check_arg_id(int id) { + if (next_arg_id_ > 0) { + report_error("cannot switch from automatic to manual argument indexing"); + return; + } + next_arg_id_ = -1; + do_check_arg_id(id); + } + FMT_CONSTEXPR void check_arg_id(basic_string_view) { + next_arg_id_ = -1; + } + FMT_CONSTEXPR void check_dynamic_spec(int arg_id); +}; + +FMT_END_EXPORT + +namespace detail { + +// Constructs fmt::basic_string_view from types implicitly convertible +// to it, deducing Char. Explicitly convertible types such as the ones returned +// from FMT_STRING are intentionally excluded. +template ::value)> +constexpr auto to_string_view(const Char* s) -> basic_string_view { + return s; +} +template ::value)> +constexpr auto to_string_view(const T& s) + -> basic_string_view { + return s; +} +template +constexpr auto to_string_view(basic_string_view s) + -> basic_string_view { + return s; +} + +template +struct has_to_string_view : std::false_type {}; +// detail:: is intentional since to_string_view is not an extension point. +template +struct has_to_string_view< + T, void_t()))>> + : std::true_type {}; + +/// String's character (code unit) type. detail:: is intentional to prevent ADL. +template ()))> +using char_t = typename V::value_type; + +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template +struct type_constant : std::integral_constant {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template \ + struct type_constant \ + : std::integral_constant {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_opt, int128_type); +FMT_TYPE_CONSTANT(uint128_opt, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr auto is_integral_type(type t) -> bool { + return t > type::none_type && t <= type::last_integer_type; +} +constexpr auto is_arithmetic_type(type t) -> bool { + return t > type::none_type && t <= type::last_numeric_type; +} + +constexpr auto set(type rhs) -> int { return 1 << static_cast(rhs); } +constexpr auto in(type t, int set) -> bool { + return ((set >> static_cast(t)) & 1) != 0; +} + +// Bitsets of types. +enum { + sint_set = + set(type::int_type) | set(type::long_long_type) | set(type::int128_type), + uint_set = set(type::uint_type) | set(type::ulong_long_type) | + set(type::uint128_type), + bool_set = set(type::bool_type), + char_set = set(type::char_type), + float_set = set(type::float_type) | set(type::double_type) | + set(type::long_double_type), + string_set = set(type::string_type), + cstring_set = set(type::cstring_type), + pointer_set = set(type::pointer_type) +}; + +struct view {}; + +template +struct is_view : std::false_type {}; +template +struct is_view> : std::is_base_of {}; + +template struct named_arg; +template struct is_named_arg : std::false_type {}; +template struct is_static_named_arg : std::false_type {}; + +template +struct is_named_arg> : std::true_type {}; + +template struct named_arg : view { + const Char* name; + const T& value; + + named_arg(const Char* n, const T& v) : name(n), value(v) {} + static_assert(!is_named_arg::value, "nested named arguments"); +}; + +template constexpr auto count() -> int { return B ? 1 : 0; } +template constexpr auto count() -> int { + return (B1 ? 1 : 0) + count(); +} + +template constexpr auto count_named_args() -> int { + return count::value...>(); +} +template constexpr auto count_static_named_args() -> int { + return count::value...>(); +} + +template struct named_arg_info { + const Char* name; + int id; +}; + +// named_args is non-const to suppress a bogus -Wmaybe-uninitalized in gcc 13. +template +FMT_CONSTEXPR void check_for_duplicate(named_arg_info* named_args, + int named_arg_index, + basic_string_view arg_name) { + for (int i = 0; i < named_arg_index; ++i) { + if (named_args[i].name == arg_name) report_error("duplicate named arg"); + } +} + +template ::value)> +void init_named_arg(named_arg_info*, int& arg_index, int&, const T&) { + ++arg_index; +} +template ::value)> +void init_named_arg(named_arg_info* named_args, int& arg_index, + int& named_arg_index, const T& arg) { + check_for_duplicate(named_args, named_arg_index, arg.name); + named_args[named_arg_index++] = {arg.name, arg_index++}; +} + +template ::value)> +FMT_CONSTEXPR void init_static_named_arg(named_arg_info*, int& arg_index, + int&) { + ++arg_index; +} +template ::value)> +FMT_CONSTEXPR void init_static_named_arg(named_arg_info* named_args, + int& arg_index, int& named_arg_index) { + check_for_duplicate(named_args, named_arg_index, T::name); + named_args[named_arg_index++] = {T::name, arg_index++}; +} + +// To minimize the number of types we need to deal with, long is translated +// either to int or to long long depending on its size. +enum { long_short = sizeof(long) == sizeof(int) && FMT_BUILTIN_TYPES }; +using long_type = conditional_t; +using ulong_type = conditional_t; + +template +using format_as_result = + remove_cvref_t()))>; +template +using format_as_member_result = + remove_cvref_t::format_as(std::declval()))>; + +template +struct use_format_as : std::false_type {}; +// format_as member is only used to avoid injection into the std namespace. +template +struct use_format_as_member : std::false_type {}; + +// Only map owning types because mapping views can be unsafe. +template +struct use_format_as< + T, bool_constant>::value>> + : std::true_type {}; +template +struct use_format_as_member< + T, bool_constant>::value>> + : std::true_type {}; + +template > +using use_formatter = + bool_constant<(std::is_class::value || std::is_enum::value || + std::is_union::value || std::is_array::value) && + !has_to_string_view::value && !is_named_arg::value && + !use_format_as::value && !use_format_as_member::value>; + +template > +auto has_formatter_impl(T* p, buffered_context* ctx = nullptr) + -> decltype(formatter().format(*p, *ctx), std::true_type()); +template auto has_formatter_impl(...) -> std::false_type; + +// T can be const-qualified to check if it is const-formattable. +template constexpr auto has_formatter() -> bool { + return decltype(has_formatter_impl(static_cast(nullptr)))::value; +} + +// Maps formatting argument types to natively supported types or user-defined +// types with formatters. Returns void on errors to be SFINAE-friendly. +template struct type_mapper { + static auto map(signed char) -> int; + static auto map(unsigned char) -> unsigned; + static auto map(short) -> int; + static auto map(unsigned short) -> unsigned; + static auto map(int) -> int; + static auto map(unsigned) -> unsigned; + static auto map(long) -> long_type; + static auto map(unsigned long) -> ulong_type; + static auto map(long long) -> long long; + static auto map(unsigned long long) -> unsigned long long; + static auto map(int128_opt) -> int128_opt; + static auto map(uint128_opt) -> uint128_opt; + static auto map(bool) -> bool; + + template + static auto map(bitint) -> conditional_t; + template + static auto map(ubitint) + -> conditional_t; + + template ::value)> + static auto map(T) -> conditional_t< + std::is_same::value || std::is_same::value, Char, void>; + + static auto map(float) -> float; + static auto map(double) -> double; + static auto map(long double) -> long double; + + static auto map(Char*) -> const Char*; + static auto map(const Char*) -> const Char*; + template , + FMT_ENABLE_IF(!std::is_pointer::value)> + static auto map(const T&) -> conditional_t::value, + basic_string_view, void>; + + static auto map(void*) -> const void*; + static auto map(const void*) -> const void*; + static auto map(volatile void*) -> const void*; + static auto map(const volatile void*) -> const void*; + static auto map(nullptr_t) -> const void*; + template ::value || + std::is_member_pointer::value)> + static auto map(const T&) -> void; + + template ::value)> + static auto map(const T& x) -> decltype(map(format_as(x))); + template ::value)> + static auto map(const T& x) -> decltype(map(formatter::format_as(x))); + + template ::value)> + static auto map(T&) -> conditional_t(), T&, void>; + + template ::value)> + static auto map(const T& named_arg) -> decltype(map(named_arg.value)); +}; + +// detail:: is used to workaround a bug in MSVC 2017. +template +using mapped_t = decltype(detail::type_mapper::map(std::declval())); + +// A type constant after applying type_mapper. +template +using mapped_type_constant = type_constant, Char>; + +template ::value> +using stored_type_constant = std::integral_constant< + type, Context::builtin_types || TYPE == type::int_type ? TYPE + : type::custom_type>; +// A parse context with extra data used only in compile-time checks. +template +class compile_parse_context : public parse_context { + private: + int num_args_; + const type* types_; + using base = parse_context; + + public: + FMT_CONSTEXPR explicit compile_parse_context(basic_string_view fmt, + int num_args, const type* types, + int next_arg_id = 0) + : base(fmt, next_arg_id), num_args_(num_args), types_(types) {} + + constexpr auto num_args() const -> int { return num_args_; } + constexpr auto arg_type(int id) const -> type { return types_[id]; } + + FMT_CONSTEXPR auto next_arg_id() -> int { + int id = base::next_arg_id(); + if (id >= num_args_) report_error("argument not found"); + return id; + } + + FMT_CONSTEXPR void check_arg_id(int id) { + base::check_arg_id(id); + if (id >= num_args_) report_error("argument not found"); + } + using base::check_arg_id; + + FMT_CONSTEXPR void check_dynamic_spec(int arg_id) { + ignore_unused(arg_id); + if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id])) + report_error("width/precision is not integer"); + } +}; + +// An argument reference. +template union arg_ref { + FMT_CONSTEXPR arg_ref(int idx = 0) : index(idx) {} + FMT_CONSTEXPR arg_ref(basic_string_view n) : name(n) {} + + int index; + basic_string_view name; +}; + +// Format specifiers with width and precision resolved at formatting rather +// than parsing time to allow reusing the same parsed specifiers with +// different sets of arguments (precompilation of format strings). +template struct dynamic_format_specs : format_specs { + arg_ref width_ref; + arg_ref precision_ref; +}; + +// Converts a character to ASCII. Returns '\0' on conversion failure. +template ::value)> +constexpr auto to_ascii(Char c) -> char { + return c <= 0xff ? static_cast(c) : '\0'; +} + +// Returns the number of code units in a code point or 1 on error. +template +FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { + if (const_check(sizeof(Char) != 1)) return 1; + auto c = static_cast(*begin); + return static_cast((0x3a55000000000000ull >> (2 * (c >> 3))) & 3) + 1; +} + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +template +FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, + int error_value) noexcept -> int { + FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); + unsigned value = 0, prev = 0; + auto p = begin; + do { + prev = value; + value = value * 10 + unsigned(*p - '0'); + ++p; + } while (p != end && '0' <= *p && *p <= '9'); + auto num_digits = p - begin; + begin = p; + int digits10 = static_cast(sizeof(int) * CHAR_BIT * 3 / 10); + if (num_digits <= digits10) return static_cast(value); + // Check for overflow. + unsigned max = INT_MAX; + return num_digits == digits10 + 1 && + prev * 10ull + unsigned(p[-1] - '0') <= max + ? static_cast(value) + : error_value; +} + +FMT_CONSTEXPR inline auto parse_align(char c) -> align { + switch (c) { + case '<': return align::left; + case '>': return align::right; + case '^': return align::center; + } + return align::none; +} + +template constexpr auto is_name_start(Char c) -> bool { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_'; +} + +template +FMT_CONSTEXPR auto parse_arg_id(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + Char c = *begin; + if (c >= '0' && c <= '9') { + int index = 0; + if (c != '0') + index = parse_nonnegative_int(begin, end, INT_MAX); + else + ++begin; + if (begin == end || (*begin != '}' && *begin != ':')) + report_error("invalid format string"); + else + handler.on_index(index); + return begin; + } + if (FMT_OPTIMIZE_SIZE > 1 || !is_name_start(c)) { + report_error("invalid format string"); + return begin; + } + auto it = begin; + do { + ++it; + } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9'))); + handler.on_name({begin, to_unsigned(it - begin)}); + return it; +} + +template struct dynamic_spec_handler { + parse_context& ctx; + arg_ref& ref; + arg_id_kind& kind; + + FMT_CONSTEXPR void on_index(int id) { + ref = id; + kind = arg_id_kind::index; + ctx.check_arg_id(id); + ctx.check_dynamic_spec(id); + } + FMT_CONSTEXPR void on_name(basic_string_view id) { + ref = id; + kind = arg_id_kind::name; + ctx.check_arg_id(id); + } +}; + +template struct parse_dynamic_spec_result { + const Char* end; + arg_id_kind kind; +}; + +// Parses integer | "{" [arg_id] "}". +template +FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end, + int& value, arg_ref& ref, + parse_context& ctx) + -> parse_dynamic_spec_result { + FMT_ASSERT(begin != end, ""); + auto kind = arg_id_kind::none; + if ('0' <= *begin && *begin <= '9') { + int val = parse_nonnegative_int(begin, end, -1); + if (val == -1) report_error("number is too big"); + value = val; + } else { + if (*begin == '{') { + ++begin; + if (begin != end) { + Char c = *begin; + if (c == '}' || c == ':') { + int id = ctx.next_arg_id(); + ref = id; + kind = arg_id_kind::index; + ctx.check_dynamic_spec(id); + } else { + begin = parse_arg_id(begin, end, + dynamic_spec_handler{ctx, ref, kind}); + } + } + if (begin != end && *begin == '}') return {++begin, kind}; + } + report_error("invalid format string"); + } + return {begin, kind}; +} + +template +FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end, + format_specs& specs, arg_ref& width_ref, + parse_context& ctx) -> const Char* { + auto result = parse_dynamic_spec(begin, end, specs.width, width_ref, ctx); + specs.set_dynamic_width(result.kind); + return result.end; +} + +template +FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, + format_specs& specs, + arg_ref& precision_ref, + parse_context& ctx) -> const Char* { + ++begin; + if (begin == end) { + report_error("invalid precision"); + return begin; + } + auto result = + parse_dynamic_spec(begin, end, specs.precision, precision_ref, ctx); + specs.set_dynamic_precision(result.kind); + return result.end; +} + +enum class state { start, align, sign, hash, zero, width, precision, locale }; + +// Parses standard format specifiers. +template +FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end, + dynamic_format_specs& specs, + parse_context& ctx, type arg_type) + -> const Char* { + auto c = '\0'; + if (end - begin > 1) { + auto next = to_ascii(begin[1]); + c = parse_align(next) == align::none ? to_ascii(*begin) : '\0'; + } else { + if (begin == end) return begin; + c = to_ascii(*begin); + } + + struct { + state current_state = state::start; + FMT_CONSTEXPR void operator()(state s, bool valid = true) { + if (current_state >= s || !valid) + report_error("invalid format specifier"); + current_state = s; + } + } enter_state; + + using pres = presentation_type; + constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; + struct { + const Char*& begin; + format_specs& specs; + type arg_type; + + FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* { + if (!in(arg_type, set)) report_error("invalid format specifier"); + specs.set_type(pres_type); + return begin + 1; + } + } parse_presentation_type{begin, specs, arg_type}; + + for (;;) { + switch (c) { + case '<': + case '>': + case '^': + enter_state(state::align); + specs.set_align(parse_align(c)); + ++begin; + break; + case '+': + case ' ': + specs.set_sign(c == ' ' ? sign::space : sign::plus); + FMT_FALLTHROUGH; + case '-': + enter_state(state::sign, in(arg_type, sint_set | float_set)); + ++begin; + break; + case '#': + enter_state(state::hash, is_arithmetic_type(arg_type)); + specs.set_alt(); + ++begin; + break; + case '0': + enter_state(state::zero); + if (!is_arithmetic_type(arg_type)) + report_error("format specifier requires numeric argument"); + if (specs.align() == align::none) { + // Ignore 0 if align is specified for compatibility with std::format. + specs.set_align(align::numeric); + specs.set_fill('0'); + } + ++begin; + break; + // clang-format off + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case '{': + // clang-format on + enter_state(state::width); + begin = parse_width(begin, end, specs, specs.width_ref, ctx); + break; + case '.': + enter_state(state::precision, + in(arg_type, float_set | string_set | cstring_set)); + begin = parse_precision(begin, end, specs, specs.precision_ref, ctx); + break; + case 'L': + enter_state(state::locale, is_arithmetic_type(arg_type)); + specs.set_localized(); + ++begin; + break; + case 'd': return parse_presentation_type(pres::dec, integral_set); + case 'X': specs.set_upper(); FMT_FALLTHROUGH; + case 'x': return parse_presentation_type(pres::hex, integral_set); + case 'o': return parse_presentation_type(pres::oct, integral_set); + case 'B': specs.set_upper(); FMT_FALLTHROUGH; + case 'b': return parse_presentation_type(pres::bin, integral_set); + case 'E': specs.set_upper(); FMT_FALLTHROUGH; + case 'e': return parse_presentation_type(pres::exp, float_set); + case 'F': specs.set_upper(); FMT_FALLTHROUGH; + case 'f': return parse_presentation_type(pres::fixed, float_set); + case 'G': specs.set_upper(); FMT_FALLTHROUGH; + case 'g': return parse_presentation_type(pres::general, float_set); + case 'A': specs.set_upper(); FMT_FALLTHROUGH; + case 'a': return parse_presentation_type(pres::hexfloat, float_set); + case 'c': + if (arg_type == type::bool_type) report_error("invalid format specifier"); + return parse_presentation_type(pres::chr, integral_set); + case 's': + return parse_presentation_type(pres::string, + bool_set | string_set | cstring_set); + case 'p': + return parse_presentation_type(pres::pointer, pointer_set | cstring_set); + case '?': + return parse_presentation_type(pres::debug, + char_set | string_set | cstring_set); + case '}': return begin; + default: { + if (*begin == '}') return begin; + // Parse fill and alignment. + auto fill_end = begin + code_point_length(begin); + if (end - fill_end <= 0) { + report_error("invalid format specifier"); + return begin; + } + if (*begin == '{') { + report_error("invalid fill character '{'"); + return begin; + } + auto alignment = parse_align(to_ascii(*fill_end)); + enter_state(state::align, alignment != align::none); + specs.set_fill( + basic_string_view(begin, to_unsigned(fill_end - begin))); + specs.set_align(alignment); + begin = fill_end + 1; + } + } + if (begin == end) return begin; + c = to_ascii(*begin); + } +} + +template +FMT_CONSTEXPR FMT_INLINE auto parse_replacement_field(const Char* begin, + const Char* end, + Handler&& handler) + -> const Char* { + ++begin; + if (begin == end) { + handler.on_error("invalid format string"); + return end; + } + int arg_id = 0; + switch (*begin) { + case '}': + handler.on_replacement_field(handler.on_arg_id(), begin); + return begin + 1; + case '{': handler.on_text(begin, begin + 1); return begin + 1; + case ':': arg_id = handler.on_arg_id(); break; + default: { + struct id_adapter { + Handler& handler; + int arg_id; + + FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); } + FMT_CONSTEXPR void on_name(basic_string_view id) { + arg_id = handler.on_arg_id(id); + } + } adapter = {handler, 0}; + begin = parse_arg_id(begin, end, adapter); + arg_id = adapter.arg_id; + Char c = begin != end ? *begin : Char(); + if (c == '}') { + handler.on_replacement_field(arg_id, begin); + return begin + 1; + } + if (c != ':') { + handler.on_error("missing '}' in format string"); + return end; + } + break; + } + } + begin = handler.on_format_specs(arg_id, begin + 1, end); + if (begin == end || *begin != '}') + return handler.on_error("unknown format specifier"), end; + return begin + 1; +} + +template +FMT_CONSTEXPR void parse_format_string(basic_string_view fmt, + Handler&& handler) { + auto begin = fmt.data(), end = begin + fmt.size(); + auto p = begin; + while (p != end) { + auto c = *p++; + if (c == '{') { + handler.on_text(begin, p - 1); + begin = p = parse_replacement_field(p - 1, end, handler); + } else if (c == '}') { + if (p == end || *p != '}') + return handler.on_error("unmatched '}' in format string"); + handler.on_text(begin, p); + begin = ++p; + } + } + handler.on_text(begin, end); +} + +// Checks char specs and returns true iff the presentation type is char-like. +FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool { + auto type = specs.type(); + if (type != presentation_type::none && type != presentation_type::chr && + type != presentation_type::debug) { + return false; + } + if (specs.align() == align::numeric || specs.sign() != sign::none || + specs.alt()) { + report_error("invalid format specifier for char"); + } + return true; +} + +// A base class for compile-time strings. +struct compile_string {}; + +template +FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769). +FMT_CONSTEXPR auto invoke_parse(parse_context& ctx) -> const Char* { + using mapped_type = remove_cvref_t>; + constexpr bool formattable = + std::is_constructible>::value; + if (!formattable) return ctx.begin(); // Error is reported in the value ctor. + using formatted_type = conditional_t; + return formatter().parse(ctx); +} + +template struct arg_pack {}; + +template +class format_string_checker { + private: + type types_[max_of(1, NUM_ARGS)]; + named_arg_info named_args_[max_of(1, NUM_NAMED_ARGS)]; + compile_parse_context context_; + + using parse_func = auto (*)(parse_context&) -> const Char*; + parse_func parse_funcs_[max_of(1, NUM_ARGS)]; + + public: + template + FMT_CONSTEXPR explicit format_string_checker(basic_string_view fmt, + arg_pack) + : types_{mapped_type_constant::value...}, + named_args_{}, + context_(fmt, NUM_ARGS, types_), + parse_funcs_{&invoke_parse...} { + int arg_index = 0, named_arg_index = 0; + FMT_APPLY_VARIADIC( + init_static_named_arg(named_args_, arg_index, named_arg_index)); + ignore_unused(arg_index, named_arg_index); + } + + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + + FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + context_.check_arg_id(id); + return id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view id) -> int { + for (int i = 0; i < NUM_NAMED_ARGS; ++i) { + if (named_args_[i].name == id) return named_args_[i].id; + } + if (!DYNAMIC_NAMES) on_error("argument not found"); + return -1; + } + + FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) { + on_format_specs(id, begin, begin); // Call parse() on empty specs. + } + + FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char* end) + -> const Char* { + context_.advance_to(begin); + if (id >= 0 && id < NUM_ARGS) return parse_funcs_[id](context_); + + // If id is out of range, it means we do not know the type and cannot parse + // the format at compile time. Instead, skip over content until we finish + // the format spec, accounting for any nested replacements. + for (int bracket_count = 0; + begin != end && (bracket_count > 0 || *begin != '}'); ++begin) { + if (*begin == '{') + ++bracket_count; + else if (*begin == '}') + --bracket_count; + } + return begin; + } + + FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) { + report_error(message); + } +}; + +/// A contiguous f_memory buffer with an optional growing ability. It is an +/// internal class and shouldn't be used directly, only via `memory_buffer`. +template class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + using grow_fun = void (*)(buffer& buf, size_t capacity); + grow_fun grow_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_MSC_WARNING(suppress : 26495) + FMT_CONSTEXPR buffer(grow_fun grow, size_t sz) noexcept + : size_(sz), capacity_(sz), grow_(grow) {} + + constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0, + size_t cap = 0) noexcept + : ptr_(p), size_(sz), capacity_(cap), grow_(grow) {} + + FMT_CONSTEXPR20 ~buffer() = default; + buffer(buffer&&) = default; + + /// Sets the buffer data and capacity. + FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + auto begin() noexcept -> T* { return ptr_; } + auto end() noexcept -> T* { return ptr_ + size_; } + + auto begin() const noexcept -> const T* { return ptr_; } + auto end() const noexcept -> const T* { return ptr_ + size_; } + + /// Returns the size of this buffer. + constexpr auto size() const noexcept -> size_t { return size_; } + + /// Returns the capacity of this buffer. + constexpr auto capacity() const noexcept -> size_t { return capacity_; } + + /// Returns a pointer to the buffer data (not null-terminated). + FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; } + FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; } + + /// Clears this buffer. + FMT_CONSTEXPR void clear() { size_ = 0; } + + // Tries resizing the buffer to contain `count` elements. If T is a POD type + // the new elements may not be initialized. + FMT_CONSTEXPR void try_resize(size_t count) { + try_reserve(count); + size_ = min_of(count, capacity_); + } + + // Tries increasing the buffer capacity to `new_capacity`. It can increase the + // capacity by a smaller amount than requested but guarantees there is space + // for at least one additional element either by increasing the capacity or by + // flushing the buffer if it is full. + FMT_CONSTEXPR void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow_(*this, new_capacity); + } + + FMT_CONSTEXPR void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /// Appends data to the end of the buffer. + template +// Workaround for MSVC2019 to fix error C2893: Failed to specialize function +// template 'void fmt::v11::detail::buffer::append(const U *,const U *)'. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1940 + FMT_CONSTEXPR20 +#endif + void + append(const U* begin, const U* end) { + while (begin != end) { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + // A loop is faster than memcpy on small sizes. + T* out = ptr_ + size_; + for (size_t i = 0; i < count; ++i) out[i] = begin[i]; + size_ += count; + begin += count; + } + } + + template FMT_CONSTEXPR auto operator[](Idx index) -> T& { + return ptr_[index]; + } + template + FMT_CONSTEXPR auto operator[](Idx index) const -> const T& { + return ptr_[index]; + } +}; + +struct buffer_traits { + constexpr explicit buffer_traits(size_t) {} + constexpr auto count() const -> size_t { return 0; } + constexpr auto limit(size_t size) const -> size_t { return size; } +}; + +class fixed_buffer_traits { + private: + size_t count_ = 0; + size_t limit_; + + public: + constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} + constexpr auto count() const -> size_t { return count_; } + FMT_CONSTEXPR auto limit(size_t size) -> size_t { + size_t n = limit_ > count_ ? limit_ - count_ : 0; + count_ += size; + return min_of(size, n); + } +}; + +// A buffer that writes to an output iterator when flushed. +template +class iterator_buffer : public Traits, public buffer { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() == buffer_size) static_cast(buf).flush(); + } + + void flush() { + auto size = this->size(); + this->clear(); + const T* begin = data_; + const T* end = begin + this->limit(size); + while (begin != end) *out_++ = *begin++; + } + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), buffer(grow, data_, 0, buffer_size), out_(out) {} + iterator_buffer(iterator_buffer&& other) noexcept + : Traits(other), + buffer(grow, data_, 0, buffer_size), + out_(other.out_) {} + ~iterator_buffer() { + // Don't crash if flush fails during unwinding. + FMT_TRY { flush(); } + FMT_CATCH(...) {} + } + + auto out() -> OutputIt { + flush(); + return out_; + } + auto count() const -> size_t { return Traits::count() + this->size(); } +}; + +template +class iterator_buffer : public fixed_buffer_traits, + public buffer { + private: + T* out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() == buf.capacity()) + static_cast(buf).flush(); + } + + void flush() { + size_t n = this->limit(this->size()); + if (this->data() == out_) { + out_ += n; + this->set(data_, buffer_size); + } + this->clear(); + } + + public: + explicit iterator_buffer(T* out, size_t n = buffer_size) + : fixed_buffer_traits(n), buffer(grow, out, 0, n), out_(out) {} + iterator_buffer(iterator_buffer&& other) noexcept + : fixed_buffer_traits(other), + buffer(static_cast(other)), + out_(other.out_) { + if (this->data() != out_) { + this->set(data_, buffer_size); + this->clear(); + } + } + ~iterator_buffer() { flush(); } + + auto out() -> T* { + flush(); + return out_; + } + auto count() const -> size_t { + return fixed_buffer_traits::count() + this->size(); + } +}; + +template class iterator_buffer : public buffer { + public: + explicit iterator_buffer(T* out, size_t = 0) + : buffer([](buffer&, size_t) {}, out, 0, ~size_t()) {} + + auto out() -> T* { return &*this->end(); } +}; + +template +class container_buffer : public buffer { + private: + using value_type = typename Container::value_type; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t capacity) { + auto& self = static_cast(buf); + self.container.resize(capacity); + self.set(&self.container[0], capacity); + } + + public: + Container& container; + + explicit container_buffer(Container& c) + : buffer(grow, c.size()), container(c) {} +}; + +// A buffer that writes to a container with the contiguous storage. +template +class iterator_buffer< + OutputIt, + enable_if_t::value && + is_contiguous::value, + typename OutputIt::container_type::value_type>> + : public container_buffer { + private: + using base = container_buffer; + + public: + explicit iterator_buffer(typename OutputIt::container_type& c) : base(c) {} + explicit iterator_buffer(OutputIt out, size_t = 0) + : base(get_container(out)) {} + + auto out() -> OutputIt { return OutputIt(this->container); } +}; + +// A buffer that counts the number of code units written discarding the output. +template class counting_buffer : public buffer { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() != buffer_size) return; + static_cast(buf).count_ += buf.size(); + buf.clear(); + } + + public: + FMT_CONSTEXPR counting_buffer() : buffer(grow, data_, 0, buffer_size) {} + + constexpr auto count() const noexcept -> size_t { + return count_ + this->size(); + } +}; + +template +struct is_back_insert_iterator> : std::true_type {}; + +template +struct has_back_insert_iterator_container_append : std::false_type {}; +template +struct has_back_insert_iterator_container_append< + OutputIt, InputIt, + void_t()) + .append(std::declval(), + std::declval()))>> : std::true_type {}; + +// An optimized version of std::copy with the output value type (T). +template ::value&& + has_back_insert_iterator_container_append< + OutputIt, InputIt>::value)> +FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + get_container(out).append(begin, end); + return out; +} + +template ::value && + !has_back_insert_iterator_container_append< + OutputIt, InputIt>::value)> +FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + auto& c = get_container(out); + c.insert(c.end(), begin, end); + return out; +} + +template ::value)> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + while (begin != end) *out++ = static_cast(*begin++); + return out; +} + +template +FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { + return copy(s.begin(), s.end(), out); +} + +template +struct is_buffer_appender : std::false_type {}; +template +struct is_buffer_appender< + It, bool_constant< + is_back_insert_iterator::value && + std::is_base_of, + typename It::container_type>::value>> + : std::true_type {}; + +// Maps an output iterator to a buffer. +template ::value)> +auto get_buffer(OutputIt out) -> iterator_buffer { + return iterator_buffer(out); +} +template ::value)> +auto get_buffer(OutputIt out) -> buffer& { + return get_container(out); +} + +template +auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) { + return buf.out(); +} +template +auto get_iterator(buffer&, OutputIt out) -> OutputIt { + return out; +} + +// This type is intentionally undefined, only used for errors. +template struct type_is_unformattable_for; + +template struct string_value { + const Char* data; + size_t size; + auto str() const -> basic_string_view { return {data, size}; } +}; + +template struct custom_value { + using char_type = typename Context::char_type; + void* value; + void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); +}; + +template struct named_arg_value { + const named_arg_info* data; + size_t size; +}; + +struct custom_tag {}; + +#if !FMT_BUILTIN_TYPES +# define FMT_BUILTIN , monostate +#else +# define FMT_BUILTIN +#endif + +// A formatting argument value. +template class value { + public: + using char_type = typename Context::char_type; + + union { + monostate no_value; + int int_value; + unsigned uint_value; + long long long_long_value; + unsigned long long ulong_long_value; + int128_opt int128_value; + uint128_opt uint128_value; + bool bool_value; + char_type char_value; + float float_value; + double double_value; + long double long_double_value; + const void* pointer; + string_value string; + custom_value custom; + named_arg_value named_args; + }; + + constexpr FMT_INLINE value() : no_value() {} + constexpr FMT_INLINE value(signed char x) : int_value(x) {} + constexpr FMT_INLINE value(unsigned char x FMT_BUILTIN) : uint_value(x) {} + constexpr FMT_INLINE value(signed short x) : int_value(x) {} + constexpr FMT_INLINE value(unsigned short x FMT_BUILTIN) : uint_value(x) {} + constexpr FMT_INLINE value(int x) : int_value(x) {} + constexpr FMT_INLINE value(unsigned x FMT_BUILTIN) : uint_value(x) {} + FMT_CONSTEXPR FMT_INLINE value(long x FMT_BUILTIN) : value(long_type(x)) {} + FMT_CONSTEXPR FMT_INLINE value(unsigned long x FMT_BUILTIN) + : value(ulong_type(x)) {} + constexpr FMT_INLINE value(long long x FMT_BUILTIN) : long_long_value(x) {} + constexpr FMT_INLINE value(unsigned long long x FMT_BUILTIN) + : ulong_long_value(x) {} + FMT_INLINE value(int128_opt x FMT_BUILTIN) : int128_value(x) {} + FMT_INLINE value(uint128_opt x FMT_BUILTIN) : uint128_value(x) {} + constexpr FMT_INLINE value(bool x FMT_BUILTIN) : bool_value(x) {} + + template + constexpr FMT_INLINE value(bitint x FMT_BUILTIN) : long_long_value(x) { + static_assert(N <= 64, "unsupported _BitInt"); + } + template + constexpr FMT_INLINE value(ubitint x FMT_BUILTIN) : ulong_long_value(x) { + static_assert(N <= 64, "unsupported _BitInt"); + } + + template ::value)> + constexpr FMT_INLINE value(T x FMT_BUILTIN) : char_value(x) { + static_assert( + std::is_same::value || std::is_same::value, + "mixing character types is disallowed"); + } + + constexpr FMT_INLINE value(float x FMT_BUILTIN) : float_value(x) {} + constexpr FMT_INLINE value(double x FMT_BUILTIN) : double_value(x) {} + FMT_INLINE value(long double x FMT_BUILTIN) : long_double_value(x) {} + + FMT_CONSTEXPR FMT_INLINE value(char_type* x FMT_BUILTIN) { + string.data = x; + if (is_constant_evaluated()) string.size = 0; + } + FMT_CONSTEXPR FMT_INLINE value(const char_type* x FMT_BUILTIN) { + string.data = x; + if (is_constant_evaluated()) string.size = 0; + } + template , + FMT_ENABLE_IF(!std::is_pointer::value)> + FMT_CONSTEXPR value(const T& x FMT_BUILTIN) { + static_assert(std::is_same::value, + "mixing character types is disallowed"); + auto sv = to_string_view(x); + string.data = sv.data(); + string.size = sv.size(); + } + FMT_INLINE value(void* x FMT_BUILTIN) : pointer(x) {} + FMT_INLINE value(const void* x FMT_BUILTIN) : pointer(x) {} + FMT_INLINE value(volatile void* x FMT_BUILTIN) + : pointer(const_cast(x)) {} + FMT_INLINE value(const volatile void* x FMT_BUILTIN) + : pointer(const_cast(x)) {} + FMT_INLINE value(nullptr_t) : pointer(nullptr) {} + + template ::value || + std::is_member_pointer::value)> + value(const T&) { + // Formatting of arbitrary pointers is disallowed. If you want to format a + // pointer cast it to `void*` or `const void*`. In particular, this forbids + // formatting of `[const] volatile char*` printed as bool by iostreams. + static_assert(sizeof(T) == 0, + "formatting of non-void pointers is disallowed"); + } + + template ::value)> + value(const T& x) : value(format_as(x)) {} + template ::value)> + value(const T& x) : value(formatter::format_as(x)) {} + + template ::value)> + value(const T& named_arg) : value(named_arg.value) {} + + template ::value || !FMT_BUILTIN_TYPES)> + FMT_CONSTEXPR20 FMT_INLINE value(T& x) : value(x, custom_tag()) {} + + FMT_ALWAYS_INLINE value(const named_arg_info* args, size_t size) + : named_args{args, size} {} + + private: + template ())> + FMT_CONSTEXPR value(T& x, custom_tag) { + using value_type = remove_const_t; + // T may overload operator& e.g. std::vector::reference in libc++. + if (!is_constant_evaluated()) { + custom.value = + const_cast(&reinterpret_cast(x)); + } else { + custom.value = nullptr; +#if defined(__cpp_if_constexpr) + if constexpr (std::is_same*>::value) + custom.value = const_cast(&x); +#endif + } + custom.format = format_custom>; + } + + template ())> + FMT_CONSTEXPR value(const T&, custom_tag) { + // Cannot format an argument; to make type T formattable provide a + // formatter specialization: https://fmt.dev/latest/api.html#udt. + type_is_unformattable_for _; + } + + // Formats an argument of a custom type, such as a user-defined class. + template + static void format_custom(void* arg, parse_context& parse_ctx, + Context& ctx) { + auto f = Formatter(); + parse_ctx.advance_to(f.parse(parse_ctx)); + using qualified_type = + conditional_t(), const T, T>; + // format must be const for compatibility with std::format and compilation. + const auto& cf = f; + ctx.advance_to(cf.format(*static_cast(arg), ctx)); + } +}; + +enum { packed_arg_bits = 4 }; +// Maximum number of arguments with packed types. +enum { max_packed_args = 62 / packed_arg_bits }; +enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; +enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; + +template +struct is_output_iterator : std::false_type {}; + +template <> struct is_output_iterator : std::true_type {}; + +template +struct is_output_iterator< + It, T, + enable_if_t&>()++), + T>::value>> : std::true_type {}; + +#ifndef FMT_USE_LOCALE +# define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1) +#endif + +// A type-erased reference to an std::locale to avoid a heavy include. +class locale_ref { +#if FMT_USE_LOCALE + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + constexpr locale_ref() : locale_(nullptr) {} + template locale_ref(const Locale& loc); + + inline explicit operator bool() const noexcept { return locale_ != nullptr; } +#endif // FMT_USE_LOCALE + + public: + template auto get() const -> Locale; +}; + +template constexpr auto encode_types() -> unsigned long long { + return 0; +} + +template +constexpr auto encode_types() -> unsigned long long { + return static_cast(stored_type_constant::value) | + (encode_types() << packed_arg_bits); +} + +template +constexpr auto make_descriptor() -> unsigned long long { + return NUM_ARGS <= max_packed_args ? encode_types() + : is_unpacked_bit | NUM_ARGS; +} + +template +using arg_t = conditional_t, + basic_format_arg>; + +template +struct named_arg_store { + // args_[0].named_args points to named_args to avoid bloating format_args. + arg_t args[1 + NUM_ARGS]; + named_arg_info named_args[NUM_NAMED_ARGS]; + + template + FMT_CONSTEXPR FMT_ALWAYS_INLINE named_arg_store(T&... values) + : args{{named_args, NUM_NAMED_ARGS}, values...} { + int arg_index = 0, named_arg_index = 0; + FMT_APPLY_VARIADIC( + init_named_arg(named_args, arg_index, named_arg_index, values)); + } + + named_arg_store(named_arg_store&& rhs) { + args[0] = {named_args, NUM_NAMED_ARGS}; + for (size_t i = 1; i < sizeof(args) / sizeof(*args); ++i) + args[i] = rhs.args[i]; + for (size_t i = 0; i < NUM_NAMED_ARGS; ++i) + named_args[i] = rhs.named_args[i]; + } + + named_arg_store(const named_arg_store& rhs) = delete; + named_arg_store& operator=(const named_arg_store& rhs) = delete; + named_arg_store& operator=(named_arg_store&& rhs) = delete; + operator const arg_t*() const { return args + 1; } +}; + +// An array of references to arguments. It can be implicitly converted to +// `basic_format_args` for passing into type-erased formatting functions +// such as `vformat`. It is a plain struct to reduce binary size in debug mode. +template +struct format_arg_store { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + using type = + conditional_t[max_of(1, NUM_ARGS)], + named_arg_store>; + type args; +}; + +// TYPE can be different from type_constant, e.g. for __float128. +template struct native_formatter { + private: + dynamic_format_specs specs_; + + public: + using nonlocking = void; + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin(); + auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE); + if (const_check(TYPE == type::char_type)) check_char_specs(specs_); + return end; + } + + template + FMT_CONSTEXPR void set_debug_format(bool set = true) { + specs_.set_type(set ? presentation_type::debug : presentation_type::none); + } + + FMT_PRAGMA_CLANG(diagnostic ignored "-Wundefined-inline") + template + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()); +}; + +template +struct locking + : bool_constant::value == type::custom_type> {}; +template +struct locking>::nonlocking>> + : std::false_type {}; + +template FMT_CONSTEXPR inline auto is_locking() -> bool { + return locking::value; +} +template +FMT_CONSTEXPR inline auto is_locking() -> bool { + return locking::value || is_locking(); +} + +FMT_API void vformat_to(buffer& buf, string_view fmt, format_args args, + locale_ref loc = {}); + +#if FMT_WIN32 +FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool); +#else // format_args is passed by reference since it is defined later. +inline void vprint_mojibake(FILE*, string_view, const format_args&, bool) {} +#endif +} // namespace detail + +// The main public API. + +template +FMT_CONSTEXPR void parse_context::do_check_arg_id(int arg_id) { + // Argument id is only checked at compile time during parsing because + // formatting has its own validation. + if (detail::is_constant_evaluated() && use_constexpr_cast) { + auto ctx = static_cast*>(this); + if (arg_id >= ctx->num_args()) report_error("argument not found"); + } +} + +template +FMT_CONSTEXPR void parse_context::check_dynamic_spec(int arg_id) { + using detail::compile_parse_context; + if (detail::is_constant_evaluated() && use_constexpr_cast) + static_cast*>(this)->check_dynamic_spec(arg_id); +} + +FMT_BEGIN_EXPORT + +// An output iterator that appends to a buffer. It is used instead of +// back_insert_iterator to reduce symbol sizes and avoid dependency. +template class basic_appender { + protected: + detail::buffer* container; + + public: + using container_type = detail::buffer; + + FMT_CONSTEXPR basic_appender(detail::buffer& buf) : container(&buf) {} + + FMT_CONSTEXPR20 auto operator=(T c) -> basic_appender& { + container->push_back(c); + return *this; + } + FMT_CONSTEXPR20 auto operator*() -> basic_appender& { return *this; } + FMT_CONSTEXPR20 auto operator++() -> basic_appender& { return *this; } + FMT_CONSTEXPR20 auto operator++(int) -> basic_appender { return *this; } +}; + +// A formatting argument. Context is a template parameter for the compiled API +// where output can be unbuffered. +template class basic_format_arg { + private: + detail::value value_; + detail::type type_; + + friend class basic_format_args; + + using char_type = typename Context::char_type; + + public: + class handle { + private: + detail::custom_value custom_; + + public: + explicit handle(detail::custom_value custom) : custom_(custom) {} + + void format(parse_context& parse_ctx, Context& ctx) const { + custom_.format(custom_.value, parse_ctx, ctx); + } + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + basic_format_arg(const detail::named_arg_info* args, size_t size) + : value_(args, size) {} + template + basic_format_arg(T&& val) + : value_(val), type_(detail::stored_type_constant::value) {} + + constexpr explicit operator bool() const noexcept { + return type_ != detail::type::none_type; + } + auto type() const -> detail::type { return type_; } + + /** + * Visits an argument dispatching to the appropriate visit method based on + * the argument type. For example, if the argument type is `double` then + * `vis(value)` will be called with the value of type `double`. + */ + template + FMT_CONSTEXPR FMT_INLINE auto visit(Visitor&& vis) const -> decltype(vis(0)) { + using detail::map; + switch (type_) { + case detail::type::none_type: break; + case detail::type::int_type: return vis(value_.int_value); + case detail::type::uint_type: return vis(value_.uint_value); + case detail::type::long_long_type: return vis(value_.long_long_value); + case detail::type::ulong_long_type: return vis(value_.ulong_long_value); + case detail::type::int128_type: return vis(map(value_.int128_value)); + case detail::type::uint128_type: return vis(map(value_.uint128_value)); + case detail::type::bool_type: return vis(value_.bool_value); + case detail::type::char_type: return vis(value_.char_value); + case detail::type::float_type: return vis(value_.float_value); + case detail::type::double_type: return vis(value_.double_value); + case detail::type::long_double_type: return vis(value_.long_double_value); + case detail::type::cstring_type: return vis(value_.string.data); + case detail::type::string_type: return vis(value_.string.str()); + case detail::type::pointer_type: return vis(value_.pointer); + case detail::type::custom_type: return vis(handle(value_.custom)); + } + return vis(monostate()); + } + + auto format_custom(const char_type* parse_begin, + parse_context& parse_ctx, Context& ctx) + -> bool { + if (type_ != detail::type::custom_type) return false; + parse_ctx.advance_to(parse_begin); + value_.custom.format(value_.custom.value, parse_ctx, ctx); + return true; + } +}; + +/** + * A view of a collection of formatting arguments. To avoid lifetime issues it + * should only be used as a parameter type in type-erased functions such as + * `vformat`: + * + * void vlog(fmt::string_view fmt, fmt::format_args args); // OK + * fmt::format_args args = fmt::make_format_args(); // Dangling reference + */ +template class basic_format_args { + private: + // A descriptor that contains information about formatting arguments. + // If the number of arguments is less or equal to max_packed_args then + // argument types are passed in the descriptor. This reduces binary code size + // per formatting function call. + unsigned long long desc_; + union { + // If is_packed() returns true then argument values are stored in values_; + // otherwise they are stored in args_. This is done to improve cache + // locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const detail::value* values_; + const basic_format_arg* args_; + }; + + constexpr auto is_packed() const -> bool { + return (desc_ & detail::is_unpacked_bit) == 0; + } + constexpr auto has_named_args() const -> bool { + return (desc_ & detail::has_named_args_bit) != 0; + } + + FMT_CONSTEXPR auto type(int index) const -> detail::type { + int shift = index * detail::packed_arg_bits; + unsigned mask = (1 << detail::packed_arg_bits) - 1; + return static_cast((desc_ >> shift) & mask); + } + + template + using store = + detail::format_arg_store; + + public: + using format_arg = basic_format_arg; + + constexpr basic_format_args() : desc_(0), args_(nullptr) {} + + /// Constructs a `basic_format_args` object from `format_arg_store`. + template + constexpr FMT_ALWAYS_INLINE basic_format_args( + const store& s) + : desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)), + values_(s.args) {} + + template detail::max_packed_args)> + constexpr basic_format_args(const store& s) + : desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)), + args_(s.args) {} + + /// Constructs a `basic_format_args` object from a dynamic list of arguments. + constexpr basic_format_args(const format_arg* args, int count, + bool has_named = false) + : desc_(detail::is_unpacked_bit | detail::to_unsigned(count) | + (has_named ? +detail::has_named_args_bit : 0)), + args_(args) {} + + /// Returns the argument with the specified id. + FMT_CONSTEXPR auto get(int id) const -> format_arg { + auto arg = format_arg(); + if (!is_packed()) { + if (id < max_size()) arg = args_[id]; + return arg; + } + if (static_cast(id) >= detail::max_packed_args) return arg; + arg.type_ = type(id); + if (arg.type_ != detail::type::none_type) arg.value_ = values_[id]; + return arg; + } + + template + auto get(basic_string_view name) const -> format_arg { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template + FMT_CONSTEXPR auto get_id(basic_string_view name) const -> int { + if (!has_named_args()) return -1; + const auto& named_args = + (is_packed() ? values_[-1] : args_[-1].value_).named_args; + for (size_t i = 0; i < named_args.size; ++i) { + if (named_args.data[i].name == name) return named_args.data[i].id; + } + return -1; + } + + auto max_size() const -> int { + unsigned long long max_packed = detail::max_packed_args; + return static_cast(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +// A formatting context. +class context { + private: + appender out_; + format_args args_; + FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_; + + public: + /// The character type for the output. + using char_type = char; + + using iterator = appender; + using format_arg = basic_format_arg; + using parse_context_type FMT_DEPRECATED = parse_context<>; + template using formatter_type FMT_DEPRECATED = formatter; + enum { builtin_types = FMT_BUILTIN_TYPES }; + + /// Constructs a `context` object. References to the arguments are stored + /// in the object so make sure they have appropriate lifetimes. + FMT_CONSTEXPR context(iterator out, format_args args, + detail::locale_ref loc = {}) + : out_(out), args_(args), loc_(loc) {} + context(context&&) = default; + context(const context&) = delete; + void operator=(const context&) = delete; + + FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); } + inline auto arg(string_view name) const -> format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(string_view name) const -> int { + return args_.get_id(name); + } + auto args() const -> const format_args& { return args_; } + + // Returns an iterator to the beginning of the output range. + FMT_CONSTEXPR auto out() const -> iterator { return out_; } + + // Advances the begin iterator to `it`. + FMT_CONSTEXPR void advance_to(iterator) {} + + FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; } +}; + +template struct runtime_format_string { + basic_string_view str; +}; + +/** + * Creates a runtime format string. + * + * **Example**: + * + * // Check format string at runtime instead of compile-time. + * fmt::print(fmt::runtime("{:d}"), "I am not a number"); + */ +inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } + +/// A compile-time format string. Use `format_string` in the public API to +/// prevent type deduction. +template struct fstring { + private: + static constexpr int num_static_named_args = + detail::count_static_named_args(); + + using checker = detail::format_string_checker< + char, static_cast(sizeof...(T)), num_static_named_args, + num_static_named_args != detail::count_named_args()>; + + using arg_pack = detail::arg_pack; + + public: + string_view str; + using t = fstring; + + // Reports a compile-time error if S is not a valid format string for T. + template + FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const char (&s)[N]) : str(s, N - 1) { + using namespace detail; + static_assert(count<(is_view>::value && + std::is_reference::value)...>() == 0, + "passing views as lvalues is disallowed"); + if (FMT_USE_CONSTEVAL) parse_format_string(s, checker(s, arg_pack())); +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert( + FMT_USE_CONSTEVAL && sizeof(s) != 0, + "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING"); +#endif + } + template ::value)> + FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) { + auto sv = string_view(str); + if (FMT_USE_CONSTEVAL) + detail::parse_format_string(sv, checker(sv, arg_pack())); +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert( + FMT_USE_CONSTEVAL && sizeof(s) != 0, + "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING"); +#endif + } + template ::value&& + std::is_same::value)> + FMT_ALWAYS_INLINE fstring(const S&) : str(S()) { + FMT_CONSTEXPR auto sv = string_view(S()); + FMT_CONSTEXPR int unused = + (parse_format_string(sv, checker(sv, arg_pack())), 0); + detail::ignore_unused(unused); + } + fstring(runtime_format_string<> fmt) : str(fmt.str) {} + + // Returning by reference generates better code in debug mode. + FMT_ALWAYS_INLINE operator const string_view&() const { return str; } + auto get() const -> string_view { return str; } +}; + +template using format_string = typename fstring::t; + +template +using is_formattable = bool_constant::value, int*, T>, Char>, + void>::value>; +#ifdef __cpp_concepts +template +concept formattable = is_formattable, Char>::value; +#endif + +template +using has_formatter FMT_DEPRECATED = std::is_constructible>; + +// A formatter specialization for natively supported types. +template +struct formatter::value != + detail::type::custom_type>> + : detail::native_formatter::value> { +}; + +/** + * Constructs an object that stores references to arguments and can be + * implicitly converted to `format_args`. `Context` can be omitted in which case + * it defaults to `context`. See `arg` for lifetime considerations. + */ +// Take arguments by lvalue references to avoid some lifetime issues, e.g. +// auto args = make_format_args(std::string()); +template (), + unsigned long long DESC = detail::make_descriptor()> +constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args) + -> detail::format_arg_store { + // Suppress warnings for pathological types convertible to detail::value. + FMT_PRAGMA_GCC(diagnostic ignored "-Wconversion") + return {{args...}}; +} + +template +using vargs = + detail::format_arg_store(), + detail::make_descriptor()>; + +/** + * Returns a named argument to be used in a formatting function. + * It should only be used in a call to a formatting function. + * + * **Example**: + * + * fmt::print("The answer is {answer}.", fmt::arg("answer", 42)); + */ +template +inline auto arg(const Char* name, const T& arg) -> detail::named_arg { + return {name, arg}; +} + +/// Formats a string and writes the output to `out`. +template , + char>::value)> +auto vformat_to(OutputIt&& out, string_view fmt, format_args args) + -> remove_cvref_t { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, fmt, args, {}); + return detail::get_iterator(buf, out); +} + +/** + * Formats `args` according to specifications in `fmt`, writes the result to + * the output iterator `out` and returns the iterator past the end of the output + * range. `format_to` does not append a terminating null character. + * + * **Example**: + * + * auto out = std::vector(); + * fmt::format_to(std::back_inserter(out), "{}", 42); + */ +template , + char>::value)> +FMT_INLINE auto format_to(OutputIt&& out, format_string fmt, T&&... args) + -> remove_cvref_t { + return vformat_to(out, fmt.str, vargs{{args...}}); +} + +template struct format_to_n_result { + /// Iterator past the end of the output range. + OutputIt out; + /// Total (not truncated) output size. + size_t size; +}; + +template ::value)> +auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + detail::vformat_to(buf, fmt, args, {}); + return {buf.out(), buf.count()}; +} + +/** + * Formats `args` according to specifications in `fmt`, writes up to `n` + * characters of the result to the output iterator `out` and returns the total + * (not truncated) output size and the iterator past the end of the output + * range. `format_to_n` does not append a terminating null character. + */ +template ::value)> +FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string fmt, + T&&... args) -> format_to_n_result { + return vformat_to_n(out, n, fmt.str, vargs{{args...}}); +} + +struct format_to_result { + /// Pointer to just after the last successful write in the array. + char* out; + /// Specifies if the output was truncated. + bool truncated; + + FMT_CONSTEXPR operator char*() const { + // Report truncation to prevent silent data loss. + if (truncated) report_error("output is truncated"); + return out; + } +}; + +template +auto vformat_to(char (&out)[N], string_view fmt, format_args args) + -> format_to_result { + auto result = vformat_to_n(out, N, fmt, args); + return {result.out, result.size > N}; +} + +template +FMT_INLINE auto format_to(char (&out)[N], format_string fmt, T&&... args) + -> format_to_result { + auto result = vformat_to_n(out, N, fmt.str, vargs{{args...}}); + return {result.out, result.size > N}; +} + +/// Returns the number of chars in the output of `format(fmt, args...)`. +template +FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, fmt.str, vargs{{args...}}, {}); + return buf.count(); +} + +FMT_API void vprint(string_view fmt, format_args args); +FMT_API void vprint(FILE* f, string_view fmt, format_args args); +FMT_API void vprintln(FILE* f, string_view fmt, format_args args); +FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args); + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::print("The answer is {}.", 42); + */ +template +FMT_INLINE void print(format_string fmt, T&&... args) { + vargs va = {{args...}}; + if (detail::const_check(!detail::use_utf8)) + return detail::vprint_mojibake(stdout, fmt.str, va, false); + return detail::is_locking() ? vprint_buffered(stdout, fmt.str, va) + : vprint(fmt.str, va); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the + * output to the file `f`. + * + * **Example**: + * + * fmt::print(stderr, "Don't {}!", "panic"); + */ +template +FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { + vargs va = {{args...}}; + if (detail::const_check(!detail::use_utf8)) + return detail::vprint_mojibake(f, fmt.str, va, false); + return detail::is_locking() ? vprint_buffered(f, fmt.str, va) + : vprint(f, fmt.str, va); +} + +/// Formats `args` according to specifications in `fmt` and writes the output +/// to the file `f` followed by a newline. +template +FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) { + vargs va = {{args...}}; + return detail::const_check(detail::use_utf8) + ? vprintln(f, fmt.str, va) + : detail::vprint_mojibake(f, fmt.str, va, true); +} + +/// Formats `args` according to specifications in `fmt` and writes the output +/// to `stdout` followed by a newline. +template +FMT_INLINE void println(format_string fmt, T&&... args) { + return fmt::println(stdout, fmt, static_cast(args)...); +} + +FMT_END_EXPORT +FMT_PRAGMA_CLANG(diagnostic pop) +FMT_PRAGMA_GCC(pop_options) +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# include "format.h" +#endif +#endif // FMT_BASE_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/chrono.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/chrono.h new file mode 100755 index 0000000000000000000000000000000000000000..e0c81589ea115626f51e4b1d29b09e578fb3af78 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/chrono.h @@ -0,0 +1,2330 @@ +// Formatting library for C++ - chrono support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CHRONO_H_ +#define FMT_CHRONO_H_ + +#ifndef FMT_MODULE +# include +# include +# include // std::isfinite +# include // std::memcpy +# include +# include +# include +# include +# include +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// Enable safe chrono durations, unless explicitly disabled. +#ifndef FMT_SAFE_DURATION_CAST +# define FMT_SAFE_DURATION_CAST 1 +#endif +#if FMT_SAFE_DURATION_CAST + +// For conversion between std::chrono::durations without undefined +// behaviour or erroneous results. +// This is a stripped down version of duration_cast, for inclusion in fmt. +// See https://github.com/pauldreik/safe_duration_cast +// +// Copyright Paul Dreik 2019 +namespace safe_duration_cast { + +template ::value && + std::numeric_limits::is_signed == + std::numeric_limits::is_signed)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + // A and B are both signed, or both unsigned. + if (detail::const_check(F::digits <= T::digits)) { + // From fits in To without any problem. + } else { + // From does not always fit in To, resort to a dynamic check. + if (from < (T::min)() || from > (T::max)()) { + // outside range. + ec = 1; + return {}; + } + } + return static_cast(from); +} + +/// Converts From to To, without loss. If the dynamic value of from +/// can't be converted to To without loss, ec is set. +template ::value && + std::numeric_limits::is_signed != + std::numeric_limits::is_signed)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + if (detail::const_check(F::is_signed && !T::is_signed)) { + // From may be negative, not allowed! + if (fmt::detail::is_negative(from)) { + ec = 1; + return {}; + } + // From is positive. Can it always fit in To? + if (detail::const_check(F::digits > T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + } + + if (detail::const_check(!F::is_signed && T::is_signed && + F::digits >= T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + return static_cast(from); // Lossless conversion. +} + +template ::value)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + return from; +} // function + +// clang-format off +/** + * converts From to To if possible, otherwise ec is set. + * + * input | output + * ---------------------------------|--------------- + * NaN | NaN + * Inf | Inf + * normal, fits in output | converted (possibly lossy) + * normal, does not fit in output | ec is set + * subnormal | best effort + * -Inf | -Inf + */ +// clang-format on +template ::value)> +FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To { + ec = 0; + using T = std::numeric_limits; + static_assert(std::is_floating_point::value, "From must be floating"); + static_assert(std::is_floating_point::value, "To must be floating"); + + // catch the only happy case + if (std::isfinite(from)) { + if (from >= T::lowest() && from <= (T::max)()) { + return static_cast(from); + } + // not within range. + ec = 1; + return {}; + } + + // nan and inf will be preserved + return static_cast(from); +} // function + +template ::value)> +FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To { + ec = 0; + static_assert(std::is_floating_point::value, "From must be floating"); + return from; +} + +/// Safe duration_cast between floating point durations +template ::value), + FMT_ENABLE_IF(std::is_floating_point::value)> +auto safe_duration_cast(std::chrono::duration from, + int& ec) -> To { + using From = std::chrono::duration; + ec = 0; + if (std::isnan(from.count())) { + // nan in, gives nan out. easy. + return To{std::numeric_limits::quiet_NaN()}; + } + // maybe we should also check if from is denormal, and decide what to do about + // it. + + // +-inf should be preserved. + if (std::isinf(from.count())) { + return To{from.count()}; + } + + // the basic idea is that we need to convert from count() in the from type + // to count() in the To type, by multiplying it with this: + struct Factor + : std::ratio_divide {}; + + static_assert(Factor::num > 0, "num must be positive"); + static_assert(Factor::den > 0, "den must be positive"); + + // the conversion is like this: multiply from.count() with Factor::num + // /Factor::den and convert it to To::rep, all this without + // overflow/underflow. let's start by finding a suitable type that can hold + // both To, From and Factor::num + using IntermediateRep = + typename std::common_type::type; + + // force conversion of From::rep -> IntermediateRep to be safe, + // even if it will never happen be narrowing in this context. + IntermediateRep count = + safe_float_conversion(from.count(), ec); + if (ec) { + return {}; + } + + // multiply with Factor::num without overflow or underflow + if (detail::const_check(Factor::num != 1)) { + constexpr auto max1 = detail::max_value() / + static_cast(Factor::num); + if (count > max1) { + ec = 1; + return {}; + } + constexpr auto min1 = std::numeric_limits::lowest() / + static_cast(Factor::num); + if (count < min1) { + ec = 1; + return {}; + } + count *= static_cast(Factor::num); + } + + // this can't go wrong, right? den>0 is checked earlier. + if (detail::const_check(Factor::den != 1)) { + using common_t = typename std::common_type::type; + count /= static_cast(Factor::den); + } + + // convert to the to type, safely + using ToRep = typename To::rep; + + const ToRep tocount = safe_float_conversion(count, ec); + if (ec) { + return {}; + } + return To{tocount}; +} +} // namespace safe_duration_cast +#endif + +namespace detail { + +// Check if std::chrono::utc_time is available. +#ifdef FMT_USE_UTC_TIME +// Use the provided definition. +#elif defined(__cpp_lib_chrono) +# define FMT_USE_UTC_TIME (__cpp_lib_chrono >= 201907L) +#else +# define FMT_USE_UTC_TIME 0 +#endif +#if FMT_USE_UTC_TIME +using utc_clock = std::chrono::utc_clock; +#else +struct utc_clock { + template void to_sys(T); +}; +#endif + +// Check if std::chrono::local_time is available. +#ifdef FMT_USE_LOCAL_TIME +// Use the provided definition. +#elif defined(__cpp_lib_chrono) +# define FMT_USE_LOCAL_TIME (__cpp_lib_chrono >= 201907L) +#else +# define FMT_USE_LOCAL_TIME 0 +#endif +#if FMT_USE_LOCAL_TIME +using local_t = std::chrono::local_t; +#else +struct local_t {}; +#endif + +} // namespace detail + +template +using sys_time = std::chrono::time_point; + +template +using utc_time = std::chrono::time_point; + +template +using local_time = std::chrono::time_point; + +namespace detail { + +// Prevents expansion of a preceding token as a function-style macro. +// Usage: f FMT_NOMACRO() +#define FMT_NOMACRO + +template struct null {}; +inline auto localtime_r FMT_NOMACRO(...) -> null<> { return null<>(); } +inline auto localtime_s(...) -> null<> { return null<>(); } +inline auto gmtime_r(...) -> null<> { return null<>(); } +inline auto gmtime_s(...) -> null<> { return null<>(); } + +// It is defined here and not in ostream.h because the latter has expensive +// includes. +template class formatbuf : public StreamBuf { + private: + using char_type = typename StreamBuf::char_type; + using streamsize = decltype(std::declval().sputn(nullptr, 0)); + using int_type = typename StreamBuf::int_type; + using traits_type = typename StreamBuf::traits_type; + + buffer& buffer_; + + public: + explicit formatbuf(buffer& buf) : buffer_(buf) {} + + protected: + // The put area is always empty. This makes the implementation simpler and has + // the advantage that the streambuf and the buffer are always in sync and + // sputc never writes into uninitialized memory. A disadvantage is that each + // call to sputc always results in a (virtual) call to overflow. There is no + // disadvantage here for sputn since this always results in a call to xsputn. + + auto overflow(int_type ch) -> int_type override { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; + +inline auto get_classic_locale() -> const std::locale& { + static const auto& locale = std::locale::classic(); + return locale; +} + +template struct codecvt_result { + static constexpr const size_t max_size = 32; + CodeUnit buf[max_size]; + CodeUnit* end; +}; + +template +void write_codecvt(codecvt_result& out, string_view in, + const std::locale& loc) { + FMT_PRAGMA_CLANG(diagnostic push) + FMT_PRAGMA_CLANG(diagnostic ignored "-Wdeprecated") + auto& f = std::use_facet>(loc); + FMT_PRAGMA_CLANG(diagnostic pop) + auto mb = std::mbstate_t(); + const char* from_next = nullptr; + auto result = f.in(mb, in.begin(), in.end(), from_next, std::begin(out.buf), + std::end(out.buf), out.end); + if (result != std::codecvt_base::ok) + FMT_THROW(format_error("failed to format time")); +} + +template +auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) + -> OutputIt { + if (const_check(detail::use_utf8) && loc != get_classic_locale()) { + // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and + // gcc-4. +#if FMT_MSC_VERSION != 0 || \ + (defined(__GLIBCXX__) && \ + (!defined(_GLIBCXX_USE_DUAL_ABI) || _GLIBCXX_USE_DUAL_ABI == 0)) + // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5 + // and newer. + using code_unit = wchar_t; +#else + using code_unit = char32_t; +#endif + + using unit_t = codecvt_result; + unit_t unit; + write_codecvt(unit, in, loc); + // In UTF-8 is used one to four one-byte code units. + auto u = + to_utf8>(); + if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)})) + FMT_THROW(format_error("failed to format time")); + return copy(u.c_str(), u.c_str() + u.size(), out); + } + return copy(in.data(), in.data() + in.size(), out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + codecvt_result unit; + write_codecvt(unit, sv, loc); + return copy(unit.buf, unit.end, out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + return write_encoded_tm_str(out, sv, loc); +} + +template +inline void do_write(buffer& buf, const std::tm& time, + const std::locale& loc, char format, char modifier) { + auto&& format_buf = formatbuf>(buf); + auto&& os = std::basic_ostream(&format_buf); + os.imbue(loc); + const auto& facet = std::use_facet>(loc); + auto end = facet.put(os, os, Char(' '), &time, format, modifier); + if (end.failed()) FMT_THROW(format_error("failed to format time")); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = get_buffer(out); + do_write(buf, time, loc, format, modifier); + return get_iterator(buf, out); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = basic_memory_buffer(); + do_write(buf, time, loc, format, modifier); + return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc); +} + +template +using is_similar_arithmetic_type = + bool_constant<(std::is_integral::value && std::is_integral::value) || + (std::is_floating_point::value && + std::is_floating_point::value)>; + +FMT_NORETURN inline void throw_duration_error() { + FMT_THROW(format_error("cannot format duration")); +} + +// Cast one integral duration to another with an overflow check. +template ::value&& + std::is_integral::value)> +auto duration_cast(std::chrono::duration from) -> To { +#if !FMT_SAFE_DURATION_CAST + return std::chrono::duration_cast(from); +#else + // The conversion factor: to.count() == factor * from.count(). + using factor = std::ratio_divide; + + using common_rep = typename std::common_type::type; + + int ec = 0; + auto count = safe_duration_cast::lossless_integral_conversion( + from.count(), ec); + if (ec) throw_duration_error(); + + // Multiply from.count() by factor and check for overflow. + if (const_check(factor::num != 1)) { + if (count > max_value() / factor::num) throw_duration_error(); + const auto min = (std::numeric_limits::min)() / factor::num; + if (const_check(!std::is_unsigned::value) && count < min) + throw_duration_error(); + count *= factor::num; + } + if (const_check(factor::den != 1)) count /= factor::den; + auto to = + To(safe_duration_cast::lossless_integral_conversion( + count, ec)); + if (ec) throw_duration_error(); + return to; +#endif +} + +template ::value&& + std::is_floating_point::value)> +auto duration_cast(std::chrono::duration from) -> To { +#if FMT_SAFE_DURATION_CAST + // Throwing version of safe_duration_cast is only available for + // integer to integer or float to float casts. + int ec; + To to = safe_duration_cast::safe_duration_cast(from, ec); + if (ec) throw_duration_error(); + return to; +#else + // Standard duration cast, may overflow. + return std::chrono::duration_cast(from); +#endif +} + +template ::value)> +auto duration_cast(std::chrono::duration from) -> To { + // Mixed integer <-> float cast is not supported by safe_duration_cast. + return std::chrono::duration_cast(from); +} + +template +auto to_time_t(sys_time time_point) -> std::time_t { + // Cannot use std::chrono::system_clock::to_time_t since this would first + // require a cast to std::chrono::system_clock::time_point, which could + // overflow. + return detail::duration_cast>( + time_point.time_since_epoch()) + .count(); +} + +namespace tz { + +// DEPRECATED! +struct time_zone { + template + auto to_sys(LocalTime) -> sys_time { + return {}; + } +}; +template auto current_zone(T...) -> time_zone* { + return nullptr; +} + +template void _tzset(T...) {} +} // namespace tz + +// DEPRECATED! +inline void tzset_once() { + static bool init = []() { + using namespace tz; + _tzset(); + return false; + }(); + ignore_unused(init); +} +} // namespace detail + +FMT_BEGIN_EXPORT + +/** + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in local time. Unlike `std::localtime`, this function is + * thread-safe on most platforms. + */ +FMT_DEPRECATED inline auto localtime(std::time_t time) -> std::tm { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + inline dispatcher(std::time_t t) : time_(t) {} + + inline auto run() -> bool { + using namespace fmt::detail; + return handle(localtime_r(&time_, &tm_)); + } + + inline auto handle(std::tm* tm) -> bool { return tm != nullptr; } + + inline auto handle(detail::null<>) -> bool { + using namespace fmt::detail; + return fallback(localtime_s(&tm_, &time_)); + } + + inline auto fallback(int res) -> bool { return res == 0; } + +#if !FMT_MSC_VERSION + inline auto fallback(detail::null<>) -> bool { + using namespace fmt::detail; + std::tm* tm = std::localtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + dispatcher lt(time); + // Too big time values may be unsupported. + if (!lt.run()) FMT_THROW(format_error("time_t value out of range")); + return lt.tm_; +} + +#if FMT_USE_LOCAL_TIME +template +FMT_DEPRECATED auto localtime(std::chrono::local_time time) + -> std::tm { + using namespace std::chrono; + using namespace detail::tz; + return localtime(detail::to_time_t(current_zone()->to_sys(time))); +} +#endif + +/** + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in Coordinated Universal Time (UTC). Unlike `std::gmtime`, this + * function is thread-safe on most platforms. + */ +inline auto gmtime(std::time_t time) -> std::tm { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + inline dispatcher(std::time_t t) : time_(t) {} + + inline auto run() -> bool { + using namespace fmt::detail; + return handle(gmtime_r(&time_, &tm_)); + } + + inline auto handle(std::tm* tm) -> bool { return tm != nullptr; } + + inline auto handle(detail::null<>) -> bool { + using namespace fmt::detail; + return fallback(gmtime_s(&tm_, &time_)); + } + + inline auto fallback(int res) -> bool { return res == 0; } + +#if !FMT_MSC_VERSION + inline auto fallback(detail::null<>) -> bool { + std::tm* tm = std::gmtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + auto gt = dispatcher(time); + // Too big time values may be unsupported. + if (!gt.run()) FMT_THROW(format_error("time_t value out of range")); + return gt.tm_; +} + +template +inline auto gmtime(sys_time time_point) -> std::tm { + return gmtime(detail::to_time_t(time_point)); +} + +namespace detail { + +// Writes two-digit numbers a, b and c separated by sep to buf. +// The method by Pavel Novikov based on +// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/. +inline void write_digit2_separated(char* buf, unsigned a, unsigned b, + unsigned c, char sep) { + unsigned long long digits = + a | (b << 24) | (static_cast(c) << 48); + // Convert each value to BCD. + // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b. + // The difference is + // y - x = a * 6 + // a can be found from x: + // a = floor(x / 10) + // then + // y = x + a * 6 = x + floor(x / 10) * 6 + // floor(x / 10) is (x * 205) >> 11 (needs 16 bits). + digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6; + // Put low nibbles to high bytes and high nibbles to low bytes. + digits = ((digits & 0x00f00000f00000f0) >> 4) | + ((digits & 0x000f00000f00000f) << 8); + auto usep = static_cast(sep); + // Add ASCII '0' to each digit byte and insert separators. + digits |= 0x3030003030003030 | (usep << 16) | (usep << 40); + + constexpr const size_t len = 8; + if (const_check(is_big_endian())) { + char tmp[len]; + std::memcpy(tmp, &digits, len); + std::reverse_copy(tmp, tmp + len, buf); + } else { + std::memcpy(buf, &digits, len); + } +} + +template +FMT_CONSTEXPR inline auto get_units() -> const char* { + if (std::is_same::value) return "as"; + if (std::is_same::value) return "fs"; + if (std::is_same::value) return "ps"; + if (std::is_same::value) return "ns"; + if (std::is_same::value) + return detail::use_utf8 ? "µs" : "us"; + if (std::is_same::value) return "ms"; + if (std::is_same::value) return "cs"; + if (std::is_same::value) return "ds"; + if (std::is_same>::value) return "s"; + if (std::is_same::value) return "das"; + if (std::is_same::value) return "hs"; + if (std::is_same::value) return "ks"; + if (std::is_same::value) return "Ms"; + if (std::is_same::value) return "Gs"; + if (std::is_same::value) return "Ts"; + if (std::is_same::value) return "Ps"; + if (std::is_same::value) return "Es"; + if (std::is_same>::value) return "min"; + if (std::is_same>::value) return "h"; + if (std::is_same>::value) return "d"; + return nullptr; +} + +enum class numeric_system { + standard, + // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale. + alternative +}; + +// Glibc extensions for formatting numeric values. +enum class pad_type { + // Pad a numeric result string with zeros (the default). + zero, + // Do not pad a numeric result string. + none, + // Pad a numeric result string with spaces. + space, +}; + +template +auto write_padding(OutputIt out, pad_type pad, int width) -> OutputIt { + if (pad == pad_type::none) return out; + return detail::fill_n(out, width, pad == pad_type::space ? ' ' : '0'); +} + +template +auto write_padding(OutputIt out, pad_type pad) -> OutputIt { + if (pad != pad_type::none) *out++ = pad == pad_type::space ? ' ' : '0'; + return out; +} + +// Parses a put_time-like format string and invokes handler actions. +template +FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + if (begin == end || *begin == '}') return begin; + if (*begin != '%') FMT_THROW(format_error("invalid format")); + auto ptr = begin; + while (ptr != end) { + pad_type pad = pad_type::zero; + auto c = *ptr; + if (c == '}') break; + if (c != '%') { + ++ptr; + continue; + } + if (begin != ptr) handler.on_text(begin, ptr); + ++ptr; // consume '%' + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr; + switch (c) { + case '_': + pad = pad_type::space; + ++ptr; + break; + case '-': + pad = pad_type::none; + ++ptr; + break; + } + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case '%': handler.on_text(ptr - 1, ptr); break; + case 'n': { + const Char newline[] = {'\n'}; + handler.on_text(newline, newline + 1); + break; + } + case 't': { + const Char tab[] = {'\t'}; + handler.on_text(tab, tab + 1); + break; + } + // Year: + case 'Y': handler.on_year(numeric_system::standard, pad); break; + case 'y': handler.on_short_year(numeric_system::standard); break; + case 'C': handler.on_century(numeric_system::standard); break; + case 'G': handler.on_iso_week_based_year(); break; + case 'g': handler.on_iso_week_based_short_year(); break; + // Day of the week: + case 'a': handler.on_abbr_weekday(); break; + case 'A': handler.on_full_weekday(); break; + case 'w': handler.on_dec0_weekday(numeric_system::standard); break; + case 'u': handler.on_dec1_weekday(numeric_system::standard); break; + // Month: + case 'b': + case 'h': handler.on_abbr_month(); break; + case 'B': handler.on_full_month(); break; + case 'm': handler.on_dec_month(numeric_system::standard, pad); break; + // Day of the year/month: + case 'U': + handler.on_dec0_week_of_year(numeric_system::standard, pad); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::standard, pad); + break; + case 'V': handler.on_iso_week_of_year(numeric_system::standard, pad); break; + case 'j': handler.on_day_of_year(pad); break; + case 'd': handler.on_day_of_month(numeric_system::standard, pad); break; + case 'e': + handler.on_day_of_month(numeric_system::standard, pad_type::space); + break; + // Hour, minute, second: + case 'H': handler.on_24_hour(numeric_system::standard, pad); break; + case 'I': handler.on_12_hour(numeric_system::standard, pad); break; + case 'M': handler.on_minute(numeric_system::standard, pad); break; + case 'S': handler.on_second(numeric_system::standard, pad); break; + // Other: + case 'c': handler.on_datetime(numeric_system::standard); break; + case 'x': handler.on_loc_date(numeric_system::standard); break; + case 'X': handler.on_loc_time(numeric_system::standard); break; + case 'D': handler.on_us_date(); break; + case 'F': handler.on_iso_date(); break; + case 'r': handler.on_12_hour_time(); break; + case 'R': handler.on_24_hour_time(); break; + case 'T': handler.on_iso_time(); break; + case 'p': handler.on_am_pm(); break; + case 'Q': handler.on_duration_value(); break; + case 'q': handler.on_duration_unit(); break; + case 'z': handler.on_utc_offset(numeric_system::standard); break; + case 'Z': handler.on_tz_name(); break; + // Alternative representation: + case 'E': { + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case 'Y': handler.on_year(numeric_system::alternative, pad); break; + case 'y': handler.on_offset_year(); break; + case 'C': handler.on_century(numeric_system::alternative); break; + case 'c': handler.on_datetime(numeric_system::alternative); break; + case 'x': handler.on_loc_date(numeric_system::alternative); break; + case 'X': handler.on_loc_time(numeric_system::alternative); break; + case 'z': handler.on_utc_offset(numeric_system::alternative); break; + default: FMT_THROW(format_error("invalid format")); + } + break; + } + case 'O': + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case 'y': handler.on_short_year(numeric_system::alternative); break; + case 'm': handler.on_dec_month(numeric_system::alternative, pad); break; + case 'U': + handler.on_dec0_week_of_year(numeric_system::alternative, pad); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::alternative, pad); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::alternative, pad); + break; + case 'd': + handler.on_day_of_month(numeric_system::alternative, pad); + break; + case 'e': + handler.on_day_of_month(numeric_system::alternative, pad_type::space); + break; + case 'w': handler.on_dec0_weekday(numeric_system::alternative); break; + case 'u': handler.on_dec1_weekday(numeric_system::alternative); break; + case 'H': handler.on_24_hour(numeric_system::alternative, pad); break; + case 'I': handler.on_12_hour(numeric_system::alternative, pad); break; + case 'M': handler.on_minute(numeric_system::alternative, pad); break; + case 'S': handler.on_second(numeric_system::alternative, pad); break; + case 'z': handler.on_utc_offset(numeric_system::alternative); break; + default: FMT_THROW(format_error("invalid format")); + } + break; + default: FMT_THROW(format_error("invalid format")); + } + begin = ptr; + } + if (begin != ptr) handler.on_text(begin, ptr); + return ptr; +} + +template struct null_chrono_spec_handler { + FMT_CONSTEXPR void unsupported() { + static_cast(this)->unsupported(); + } + FMT_CONSTEXPR void on_year(numeric_system, pad_type) { unsupported(); } + FMT_CONSTEXPR void on_short_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_offset_year() { unsupported(); } + FMT_CONSTEXPR void on_century(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_short_year() { unsupported(); } + FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); } + FMT_CONSTEXPR void on_full_weekday() { unsupported(); } + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_abbr_month() { unsupported(); } + FMT_CONSTEXPR void on_full_month() { unsupported(); } + FMT_CONSTEXPR void on_dec_month(numeric_system, pad_type) { unsupported(); } + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_day_of_year(pad_type) { unsupported(); } + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_us_date() { unsupported(); } + FMT_CONSTEXPR void on_iso_date() { unsupported(); } + FMT_CONSTEXPR void on_12_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_24_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_iso_time() { unsupported(); } + FMT_CONSTEXPR void on_am_pm() { unsupported(); } + FMT_CONSTEXPR void on_duration_value() { unsupported(); } + FMT_CONSTEXPR void on_duration_unit() { unsupported(); } + FMT_CONSTEXPR void on_utc_offset(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_tz_name() { unsupported(); } +}; + +class tm_format_checker : public null_chrono_spec_handler { + private: + bool has_timezone_ = false; + + public: + constexpr explicit tm_format_checker(bool has_timezone) + : has_timezone_(has_timezone) {} + + FMT_NORETURN inline void unsupported() { + FMT_THROW(format_error("no format")); + } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_short_year(numeric_system) {} + FMT_CONSTEXPR void on_offset_year() {} + FMT_CONSTEXPR void on_century(numeric_system) {} + FMT_CONSTEXPR void on_iso_week_based_year() {} + FMT_CONSTEXPR void on_iso_week_based_short_year() {} + FMT_CONSTEXPR void on_abbr_weekday() {} + FMT_CONSTEXPR void on_full_weekday() {} + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) {} + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) {} + FMT_CONSTEXPR void on_abbr_month() {} + FMT_CONSTEXPR void on_full_month() {} + FMT_CONSTEXPR void on_dec_month(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_day_of_year(pad_type) {} + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_second(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_datetime(numeric_system) {} + FMT_CONSTEXPR void on_loc_date(numeric_system) {} + FMT_CONSTEXPR void on_loc_time(numeric_system) {} + FMT_CONSTEXPR void on_us_date() {} + FMT_CONSTEXPR void on_iso_date() {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_utc_offset(numeric_system) { + if (!has_timezone_) FMT_THROW(format_error("no timezone")); + } + FMT_CONSTEXPR void on_tz_name() { + if (!has_timezone_) FMT_THROW(format_error("no timezone")); + } +}; + +inline auto tm_wday_full_name(int wday) -> const char* { + static constexpr const char* full_name_list[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?"; +} +inline auto tm_wday_short_name(int wday) -> const char* { + static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; + return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???"; +} + +inline auto tm_mon_full_name(int mon) -> const char* { + static constexpr const char* full_name_list[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?"; +} +inline auto tm_mon_short_name(int mon) -> const char* { + static constexpr const char* short_name_list[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???"; +} + +template +struct has_tm_gmtoff : std::false_type {}; +template +struct has_tm_gmtoff> : std::true_type {}; + +template struct has_tm_zone : std::false_type {}; +template +struct has_tm_zone> : std::true_type {}; + +template ::value)> +bool set_tm_zone(T& time, char* tz) { + time.tm_zone = tz; + return true; +} +template ::value)> +bool set_tm_zone(T&, char*) { + return false; +} + +inline char* utc() { + static char tz[] = "UTC"; + return tz; +} + +// Converts value to Int and checks that it's in the range [0, upper). +template ::value)> +inline auto to_nonnegative_int(T value, Int upper) -> Int { + if (!std::is_unsigned::value && + (value < 0 || to_unsigned(value) > to_unsigned(upper))) { + FMT_THROW(format_error("chrono value is out of range")); + } + return static_cast(value); +} +template ::value)> +inline auto to_nonnegative_int(T value, Int upper) -> Int { + auto int_value = static_cast(value); + if (int_value < 0 || value > static_cast(upper)) + FMT_THROW(format_error("invalid value")); + return int_value; +} + +constexpr auto pow10(std::uint32_t n) -> long long { + return n == 0 ? 1 : 10 * pow10(n - 1); +} + +// Counts the number of fractional digits in the range [0, 18] according to the +// C++20 spec. If more than 18 fractional digits are required then returns 6 for +// microseconds precision. +template () / 10)> +struct count_fractional_digits { + static constexpr int value = + Num % Den == 0 ? N : count_fractional_digits::value; +}; + +// Base case that doesn't instantiate any more templates +// in order to avoid overflow. +template +struct count_fractional_digits { + static constexpr int value = (Num % Den == 0) ? N : 6; +}; + +// Format subseconds which are given as an integer type with an appropriate +// number of digits. +template +void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { + constexpr auto num_fractional_digits = + count_fractional_digits::value; + + using subsecond_precision = std::chrono::duration< + typename std::common_type::type, + std::ratio<1, pow10(num_fractional_digits)>>; + + const auto fractional = d - detail::duration_cast(d); + const auto subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : detail::duration_cast(fractional).count(); + auto n = static_cast>(subseconds); + const int num_digits = count_digits(n); + + int leading_zeroes = (std::max)(0, num_fractional_digits - num_digits); + if (precision < 0) { + FMT_ASSERT(!std::is_floating_point::value, ""); + if (std::ratio_less::value) { + *out++ = '.'; + out = detail::fill_n(out, leading_zeroes, '0'); + out = format_decimal(out, n, num_digits); + } + } else if (precision > 0) { + *out++ = '.'; + leading_zeroes = min_of(leading_zeroes, precision); + int remaining = precision - leading_zeroes; + out = detail::fill_n(out, leading_zeroes, '0'); + if (remaining < num_digits) { + int num_truncated_digits = num_digits - remaining; + n /= to_unsigned(pow10(to_unsigned(num_truncated_digits))); + if (n != 0) out = format_decimal(out, n, remaining); + return; + } + if (n != 0) { + out = format_decimal(out, n, num_digits); + remaining -= num_digits; + } + out = detail::fill_n(out, remaining, '0'); + } +} + +// Format subseconds which are given as a floating point type with an +// appropriate number of digits. We cannot pass the Duration here, as we +// explicitly need to pass the Rep value in the duration_formatter. +template +void write_floating_seconds(memory_buffer& buf, Duration duration, + int num_fractional_digits = -1) { + using rep = typename Duration::rep; + FMT_ASSERT(std::is_floating_point::value, ""); + + auto val = duration.count(); + + if (num_fractional_digits < 0) { + // For `std::round` with fallback to `round`: + // On some toolchains `std::round` is not available (e.g. GCC 6). + using namespace std; + num_fractional_digits = + count_fractional_digits::value; + if (num_fractional_digits < 6 && static_cast(round(val)) != val) + num_fractional_digits = 6; + } + + fmt::format_to(std::back_inserter(buf), FMT_STRING("{:.{}f}"), + std::fmod(val * static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), + num_fractional_digits); +} + +template +class tm_writer { + private: + static constexpr int days_per_week = 7; + + const std::locale& loc_; + bool is_classic_; + OutputIt out_; + const Duration* subsecs_; + const std::tm& tm_; + + auto tm_sec() const noexcept -> int { + FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, ""); + return tm_.tm_sec; + } + auto tm_min() const noexcept -> int { + FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, ""); + return tm_.tm_min; + } + auto tm_hour() const noexcept -> int { + FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, ""); + return tm_.tm_hour; + } + auto tm_mday() const noexcept -> int { + FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, ""); + return tm_.tm_mday; + } + auto tm_mon() const noexcept -> int { + FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, ""); + return tm_.tm_mon; + } + auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; } + auto tm_wday() const noexcept -> int { + FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, ""); + return tm_.tm_wday; + } + auto tm_yday() const noexcept -> int { + FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, ""); + return tm_.tm_yday; + } + + auto tm_hour12() const noexcept -> int { + auto h = tm_hour(); + auto z = h < 12 ? h : h - 12; + return z == 0 ? 12 : z; + } + + // POSIX and the C Standard are unclear or inconsistent about what %C and %y + // do if the year is negative or exceeds 9999. Use the convention that %C + // concatenated with %y yields the same output as %Y, and that %Y contains at + // least 4 characters, with more only if necessary. + auto split_year_lower(long long year) const noexcept -> int { + auto l = year % 100; + if (l < 0) l = -l; // l in [0, 99] + return static_cast(l); + } + + // Algorithm: https://en.wikipedia.org/wiki/ISO_week_date. + auto iso_year_weeks(long long curr_year) const noexcept -> int { + auto prev_year = curr_year - 1; + auto curr_p = + (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) % + days_per_week; + auto prev_p = + (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) % + days_per_week; + return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0); + } + auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int { + return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) / + days_per_week; + } + auto tm_iso_week_year() const noexcept -> long long { + auto year = tm_year(); + auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return year - 1; + if (w > iso_year_weeks(year)) return year + 1; + return year; + } + auto tm_iso_week_of_year() const noexcept -> int { + auto year = tm_year(); + auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return iso_year_weeks(year - 1); + if (w > iso_year_weeks(year)) return 1; + return w; + } + + void write1(int value) { + *out_++ = static_cast('0' + to_unsigned(value) % 10); + } + void write2(int value) { + const char* d = digits2(to_unsigned(value) % 100); + *out_++ = *d++; + *out_++ = *d; + } + void write2(int value, pad_type pad) { + unsigned int v = to_unsigned(value) % 100; + if (v >= 10) { + const char* d = digits2(v); + *out_++ = *d++; + *out_++ = *d; + } else { + out_ = detail::write_padding(out_, pad); + *out_++ = static_cast('0' + v); + } + } + + void write_year_extended(long long year, pad_type pad) { + // At least 4 characters. + int width = 4; + bool negative = year < 0; + if (negative) { + year = 0 - year; + --width; + } + uint32_or_64_or_128_t n = to_unsigned(year); + const int num_digits = count_digits(n); + if (negative && pad == pad_type::zero) *out_++ = '-'; + if (width > num_digits) + out_ = detail::write_padding(out_, pad, width - num_digits); + if (negative && pad != pad_type::zero) *out_++ = '-'; + out_ = format_decimal(out_, n, num_digits); + } + void write_year(long long year, pad_type pad) { + write_year_extended(year, pad); + } + + void write_utc_offset(long long offset, numeric_system ns) { + if (offset < 0) { + *out_++ = '-'; + offset = -offset; + } else { + *out_++ = '+'; + } + offset /= 60; + write2(static_cast(offset / 60)); + if (ns != numeric_system::standard) *out_++ = ':'; + write2(static_cast(offset % 60)); + } + + template ::value)> + void format_utc_offset(const T& tm, numeric_system ns) { + write_utc_offset(tm.tm_gmtoff, ns); + } + template ::value)> + void format_utc_offset(const T&, numeric_system ns) { + write_utc_offset(0, ns); + } + + template ::value)> + void format_tz_name(const T& tm) { + out_ = write_tm_str(out_, tm.tm_zone, loc_); + } + template ::value)> + void format_tz_name(const T&) { + out_ = std::copy_n(utc(), 3, out_); + } + + void format_localized(char format, char modifier = 0) { + out_ = write(out_, tm_, loc_, format, modifier); + } + + public: + tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm, + const Duration* subsecs = nullptr) + : loc_(loc), + is_classic_(loc_ == get_classic_locale()), + out_(out), + subsecs_(subsecs), + tm_(tm) {} + + auto out() const -> OutputIt { return out_; } + + FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { + out_ = copy(begin, end, out_); + } + + void on_abbr_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_short_name(tm_wday())); + else + format_localized('a'); + } + void on_full_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_full_name(tm_wday())); + else + format_localized('A'); + } + void on_dec0_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday()); + format_localized('w', 'O'); + } + void on_dec1_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write1(wday == 0 ? days_per_week : wday); + } else { + format_localized('u', 'O'); + } + } + + void on_abbr_month() { + if (is_classic_) + out_ = write(out_, tm_mon_short_name(tm_mon())); + else + format_localized('b'); + } + void on_full_month() { + if (is_classic_) + out_ = write(out_, tm_mon_full_name(tm_mon())); + else + format_localized('B'); + } + + void on_datetime(numeric_system ns) { + if (is_classic_) { + on_abbr_weekday(); + *out_++ = ' '; + on_abbr_month(); + *out_++ = ' '; + on_day_of_month(numeric_system::standard, pad_type::space); + *out_++ = ' '; + on_iso_time(); + *out_++ = ' '; + on_year(numeric_system::standard, pad_type::space); + } else { + format_localized('c', ns == numeric_system::standard ? '\0' : 'E'); + } + } + void on_loc_date(numeric_system ns) { + if (is_classic_) + on_us_date(); + else + format_localized('x', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_loc_time(numeric_system ns) { + if (is_classic_) + on_iso_time(); + else + format_localized('X', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_us_date() { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_mon() + 1), + to_unsigned(tm_mday()), + to_unsigned(split_year_lower(tm_year())), '/'); + out_ = copy(std::begin(buf), std::end(buf), out_); + } + void on_iso_date() { + auto year = tm_year(); + char buf[10]; + size_t offset = 0; + if (year >= 0 && year < 10000) { + write2digits(buf, static_cast(year / 100)); + } else { + offset = 4; + write_year_extended(year, pad_type::zero); + year = 0; + } + write_digit2_separated(buf + 2, static_cast(year % 100), + to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), + '-'); + out_ = copy(std::begin(buf) + offset, std::end(buf), out_); + } + + void on_utc_offset(numeric_system ns) { format_utc_offset(tm_, ns); } + void on_tz_name() { format_tz_name(tm_); } + + void on_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write_year(tm_year(), pad); + format_localized('Y', 'E'); + } + void on_short_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(split_year_lower(tm_year())); + format_localized('y', 'O'); + } + void on_offset_year() { + if (is_classic_) return write2(split_year_lower(tm_year())); + format_localized('y', 'E'); + } + + void on_century(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto year = tm_year(); + auto upper = year / 100; + if (year >= -99 && year < 0) { + // Zero upper on negative year. + *out_++ = '-'; + *out_++ = '0'; + } else if (upper >= 0 && upper < 100) { + write2(static_cast(upper)); + } else { + out_ = write(out_, upper); + } + } else { + format_localized('C', 'E'); + } + } + + void on_dec_month(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mon() + 1, pad); + format_localized('m', 'O'); + } + + void on_dec0_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week, + pad); + format_localized('U', 'O'); + } + void on_dec1_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write2((tm_yday() + days_per_week - + (wday == 0 ? (days_per_week - 1) : (wday - 1))) / + days_per_week, + pad); + } else { + format_localized('W', 'O'); + } + } + void on_iso_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_iso_week_of_year(), pad); + format_localized('V', 'O'); + } + + void on_iso_week_based_year() { + write_year(tm_iso_week_year(), pad_type::zero); + } + void on_iso_week_based_short_year() { + write2(split_year_lower(tm_iso_week_year())); + } + + void on_day_of_year(pad_type pad) { + auto yday = tm_yday() + 1; + auto digit1 = yday / 100; + if (digit1 != 0) + write1(digit1); + else + out_ = detail::write_padding(out_, pad); + write2(yday % 100, pad); + } + + void on_day_of_month(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mday(), pad); + format_localized('d', 'O'); + } + + void on_24_hour(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour(), pad); + format_localized('H', 'O'); + } + void on_12_hour(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour12(), pad); + format_localized('I', 'O'); + } + void on_minute(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_min(), pad); + format_localized('M', 'O'); + } + + void on_second(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) { + write2(tm_sec(), pad); + if (subsecs_) { + if (std::is_floating_point::value) { + auto buf = memory_buffer(); + write_floating_seconds(buf, *subsecs_); + if (buf.size() > 1) { + // Remove the leading "0", write something like ".123". + out_ = copy(buf.begin() + 1, buf.end(), out_); + } + } else { + write_fractional_seconds(out_, *subsecs_); + } + } + } else { + // Currently no formatting of subseconds when a locale is set. + format_localized('S', 'O'); + } + } + + void on_12_hour_time() { + if (is_classic_) { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour12()), + to_unsigned(tm_min()), to_unsigned(tm_sec()), ':'); + out_ = copy(std::begin(buf), std::end(buf), out_); + *out_++ = ' '; + on_am_pm(); + } else { + format_localized('r'); + } + } + void on_24_hour_time() { + write2(tm_hour()); + *out_++ = ':'; + write2(tm_min()); + } + void on_iso_time() { + on_24_hour_time(); + *out_++ = ':'; + on_second(numeric_system::standard, pad_type::zero); + } + + void on_am_pm() { + if (is_classic_) { + *out_++ = tm_hour() < 12 ? 'A' : 'P'; + *out_++ = 'M'; + } else { + format_localized('p'); + } + } + + // These apply to chrono durations but not tm. + void on_duration_value() {} + void on_duration_unit() {} +}; + +struct chrono_format_checker : null_chrono_spec_handler { + bool has_precision_integral = false; + + FMT_NORETURN inline void unsupported() { FMT_THROW(format_error("no date")); } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_day_of_year(pad_type) {} + FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_second(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_duration_value() const { + if (has_precision_integral) + FMT_THROW(format_error("precision not allowed for this argument type")); + } + FMT_CONSTEXPR void on_duration_unit() {} +}; + +template ::value&& has_isfinite::value)> +inline auto isfinite(T) -> bool { + return true; +} + +template ::value)> +inline auto mod(T x, int y) -> T { + return x % static_cast(y); +} +template ::value)> +inline auto mod(T x, int y) -> T { + return std::fmod(x, static_cast(y)); +} + +// If T is an integral type, maps T to its unsigned counterpart, otherwise +// leaves it unchanged (unlike std::make_unsigned). +template ::value> +struct make_unsigned_or_unchanged { + using type = T; +}; + +template struct make_unsigned_or_unchanged { + using type = typename std::make_unsigned::type; +}; + +template ::value)> +inline auto get_milliseconds(std::chrono::duration d) + -> std::chrono::duration { + // This may overflow and/or the result may not fit in the target type. +#if FMT_SAFE_DURATION_CAST + using common_seconds_type = + typename std::common_type::type; + auto d_as_common = detail::duration_cast(d); + auto d_as_whole_seconds = + detail::duration_cast(d_as_common); + // This conversion should be nonproblematic. + auto diff = d_as_common - d_as_whole_seconds; + auto ms = detail::duration_cast>(diff); + return ms; +#else + auto s = detail::duration_cast(d); + return detail::duration_cast(d - s); +#endif +} + +template ::value)> +auto format_duration_value(OutputIt out, Rep val, int) -> OutputIt { + return write(out, val); +} + +template ::value)> +auto format_duration_value(OutputIt out, Rep val, int precision) -> OutputIt { + auto specs = format_specs(); + specs.precision = precision; + specs.set_type(precision >= 0 ? presentation_type::fixed + : presentation_type::general); + return write(out, val, specs); +} + +template +auto copy_unit(string_view unit, OutputIt out, Char) -> OutputIt { + return copy(unit.begin(), unit.end(), out); +} + +template +auto copy_unit(string_view unit, OutputIt out, wchar_t) -> OutputIt { + // This works when wchar_t is UTF-32 because units only contain characters + // that have the same representation in UTF-16 and UTF-32. + utf8_to_utf16 u(unit); + return copy(u.c_str(), u.c_str() + u.size(), out); +} + +template +auto format_duration_unit(OutputIt out) -> OutputIt { + if (const char* unit = get_units()) + return copy_unit(string_view(unit), out, Char()); + *out++ = '['; + out = write(out, Period::num); + if (const_check(Period::den != 1)) { + *out++ = '/'; + out = write(out, Period::den); + } + *out++ = ']'; + *out++ = 's'; + return out; +} + +class get_locale { + private: + union { + std::locale locale_; + }; + bool has_locale_ = false; + + public: + inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) { + if (localized) + ::new (&locale_) std::locale(loc.template get()); + } + inline ~get_locale() { + if (has_locale_) locale_.~locale(); + } + inline operator const std::locale&() const { + return has_locale_ ? locale_ : get_classic_locale(); + } +}; + +template +struct duration_formatter { + using iterator = basic_appender; + iterator out; + // rep is unsigned to avoid overflow. + using rep = + conditional_t::value && sizeof(Rep) < sizeof(int), + unsigned, typename make_unsigned_or_unchanged::type>; + rep val; + int precision; + locale_ref locale; + bool localized = false; + using seconds = std::chrono::duration; + seconds s; + using milliseconds = std::chrono::duration; + bool negative; + + using tm_writer_type = tm_writer; + + duration_formatter(iterator o, std::chrono::duration d, + locale_ref loc) + : out(o), val(static_cast(d.count())), locale(loc), negative(false) { + if (d.count() < 0) { + val = 0 - val; + negative = true; + } + + // this may overflow and/or the result may not fit in the + // target type. + // might need checked conversion (rep!=Rep) + s = detail::duration_cast(std::chrono::duration(val)); + } + + // returns true if nan or inf, writes to out. + auto handle_nan_inf() -> bool { + if (isfinite(val)) return false; + if (isnan(val)) { + write_nan(); + return true; + } + // must be +-inf + if (val > 0) + std::copy_n("inf", 3, out); + else + std::copy_n("-inf", 4, out); + return true; + } + + auto days() const -> Rep { return static_cast(s.count() / 86400); } + auto hour() const -> Rep { + return static_cast(mod((s.count() / 3600), 24)); + } + + auto hour12() const -> Rep { + Rep hour = static_cast(mod((s.count() / 3600), 12)); + return hour <= 0 ? 12 : hour; + } + + auto minute() const -> Rep { + return static_cast(mod((s.count() / 60), 60)); + } + auto second() const -> Rep { return static_cast(mod(s.count(), 60)); } + + auto time() const -> std::tm { + auto time = std::tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + time.tm_min = to_nonnegative_int(minute(), 60); + time.tm_sec = to_nonnegative_int(second(), 60); + return time; + } + + void write_sign() { + if (!negative) return; + *out++ = '-'; + negative = false; + } + + void write(Rep value, int width, pad_type pad = pad_type::zero) { + write_sign(); + if (isnan(value)) return write_nan(); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(value, max_value())); + int num_digits = detail::count_digits(n); + if (width > num_digits) { + out = detail::write_padding(out, pad, width - num_digits); + } + out = format_decimal(out, n, num_digits); + } + + void write_nan() { std::copy_n("nan", 3, out); } + + template + void format_tm(const tm& time, Callback cb, Args... args) { + if (isnan(val)) return write_nan(); + get_locale loc(localized, locale); + auto w = tm_writer_type(loc, out, time); + (w.*cb)(args...); + out = w.out(); + } + + void on_text(const Char* begin, const Char* end) { + copy(begin, end, out); + } + + // These are not implemented because durations don't have date information. + void on_abbr_weekday() {} + void on_full_weekday() {} + void on_dec0_weekday(numeric_system) {} + void on_dec1_weekday(numeric_system) {} + void on_abbr_month() {} + void on_full_month() {} + void on_datetime(numeric_system) {} + void on_loc_date(numeric_system) {} + void on_loc_time(numeric_system) {} + void on_us_date() {} + void on_iso_date() {} + void on_utc_offset(numeric_system) {} + void on_tz_name() {} + void on_year(numeric_system, pad_type) {} + void on_short_year(numeric_system) {} + void on_offset_year() {} + void on_century(numeric_system) {} + void on_iso_week_based_year() {} + void on_iso_week_based_short_year() {} + void on_dec_month(numeric_system, pad_type) {} + void on_dec0_week_of_year(numeric_system, pad_type) {} + void on_dec1_week_of_year(numeric_system, pad_type) {} + void on_iso_week_of_year(numeric_system, pad_type) {} + void on_day_of_month(numeric_system, pad_type) {} + + void on_day_of_year(pad_type) { + if (handle_nan_inf()) return; + write(days(), 0); + } + + void on_24_hour(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour(), 2, pad); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + format_tm(time, &tm_writer_type::on_24_hour, ns, pad); + } + + void on_12_hour(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour12(), 2, pad); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour12(), 12); + format_tm(time, &tm_writer_type::on_12_hour, ns, pad); + } + + void on_minute(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(minute(), 2, pad); + auto time = tm(); + time.tm_min = to_nonnegative_int(minute(), 60); + format_tm(time, &tm_writer_type::on_minute, ns, pad); + } + + void on_second(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) { + if (std::is_floating_point::value) { + auto buf = memory_buffer(); + write_floating_seconds(buf, std::chrono::duration(val), + precision); + if (negative) *out++ = '-'; + if (buf.size() < 2 || buf[1] == '.') + out = detail::write_padding(out, pad); + out = copy(buf.begin(), buf.end(), out); + } else { + write(second(), 2, pad); + write_fractional_seconds( + out, std::chrono::duration(val), precision); + } + return; + } + auto time = tm(); + time.tm_sec = to_nonnegative_int(second(), 60); + format_tm(time, &tm_writer_type::on_second, ns, pad); + } + + void on_12_hour_time() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_12_hour_time); + } + + void on_24_hour_time() { + if (handle_nan_inf()) { + *out++ = ':'; + handle_nan_inf(); + return; + } + + write(hour(), 2); + *out++ = ':'; + write(minute(), 2); + } + + void on_iso_time() { + on_24_hour_time(); + *out++ = ':'; + if (handle_nan_inf()) return; + on_second(numeric_system::standard, pad_type::zero); + } + + void on_am_pm() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_am_pm); + } + + void on_duration_value() { + if (handle_nan_inf()) return; + write_sign(); + out = format_duration_value(out, val, precision); + } + + void on_duration_unit() { out = format_duration_unit(out); } +}; + +} // namespace detail + +#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 +using weekday = std::chrono::weekday; +using day = std::chrono::day; +using month = std::chrono::month; +using year = std::chrono::year; +using year_month_day = std::chrono::year_month_day; +#else +// A fallback version of weekday. +class weekday { + private: + unsigned char value_; + + public: + weekday() = default; + constexpr explicit weekday(unsigned wd) noexcept + : value_(static_cast(wd != 7 ? wd : 0)) {} + constexpr auto c_encoding() const noexcept -> unsigned { return value_; } +}; + +class day { + private: + unsigned char value_; + + public: + day() = default; + constexpr explicit day(unsigned d) noexcept + : value_(static_cast(d)) {} + constexpr explicit operator unsigned() const noexcept { return value_; } +}; + +class month { + private: + unsigned char value_; + + public: + month() = default; + constexpr explicit month(unsigned m) noexcept + : value_(static_cast(m)) {} + constexpr explicit operator unsigned() const noexcept { return value_; } +}; + +class year { + private: + int value_; + + public: + year() = default; + constexpr explicit year(int y) noexcept : value_(y) {} + constexpr explicit operator int() const noexcept { return value_; } +}; + +class year_month_day { + private: + fmt::year year_; + fmt::month month_; + fmt::day day_; + + public: + year_month_day() = default; + constexpr year_month_day(const year& y, const month& m, const day& d) noexcept + : year_(y), month_(m), day_(d) {} + constexpr auto year() const noexcept -> fmt::year { return year_; } + constexpr auto month() const noexcept -> fmt::month { return month_; } + constexpr auto day() const noexcept -> fmt::day { return day_; } +}; +#endif // __cpp_lib_chrono >= 201907 + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && *it == 'L') { + ++it; + this->set_localized(); + } + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_wday = static_cast(wd.c_encoding()); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(this->localized(), ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_abbr_weekday(); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(day d, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_mday = static_cast(static_cast(d)); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(false, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_day_of_month(detail::numeric_system::standard, detail::pad_type::zero); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && *it == 'L') { + ++it; + this->set_localized(); + } + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(month m, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_mon = static_cast(static_cast(m)) - 1; + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(this->localized(), ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_abbr_month(); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(year y, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_year = static_cast(y) - 1900; + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(false, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_year(detail::numeric_system::standard, detail::pad_type::zero); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(year_month_day val, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_year = static_cast(val.year()) - 1900; + time.tm_mon = static_cast(static_cast(val.month())) - 1; + time.tm_mday = static_cast(static_cast(val.day())); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(true, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_iso_date(); + return w.out(); + } +}; + +template +struct formatter, Char> { + private: + format_specs specs_; + detail::arg_ref width_ref_; + detail::arg_ref precision_ref_; + basic_string_view fmt_; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + Char c = *it; + if ((c >= '0' && c <= '9') || c == '{') { + it = detail::parse_width(it, end, specs_, width_ref_, ctx); + if (it == end) return it; + } + + auto checker = detail::chrono_format_checker(); + if (*it == '.') { + checker.has_precision_integral = !std::is_floating_point::value; + it = detail::parse_precision(it, end, specs_, precision_ref_, ctx); + } + if (it != end && *it == 'L') { + specs_.set_localized(); + ++it; + } + end = detail::parse_chrono_format(it, end, checker); + fmt_ = {it, detail::to_unsigned(end - it)}; + return end; + } + + template + auto format(std::chrono::duration d, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + auto precision = specs.precision; + specs.precision = -1; + auto begin = fmt_.begin(), end = fmt_.end(); + // As a possible future optimization, we could avoid extra copying if width + // is not specified. + auto buf = basic_memory_buffer(); + auto out = basic_appender(buf); + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_, + ctx); + detail::handle_dynamic_spec(specs.dynamic_precision(), precision, + precision_ref_, ctx); + if (begin == end || *begin == '}') { + out = detail::format_duration_value(out, d.count(), precision); + detail::format_duration_unit(out); + } else { + auto f = + detail::duration_formatter(out, d, ctx.locale()); + f.precision = precision; + f.localized = specs_.localized(); + detail::parse_chrono_format(begin, end, f); + } + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } +}; + +template struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + basic_string_view fmt_ = + detail::string_literal(); + + protected: + auto localized() const -> bool { return specs_.localized(); } + FMT_CONSTEXPR void set_localized() { specs_.set_localized(); } + + FMT_CONSTEXPR auto do_parse(parse_context& ctx, bool has_timezone) + -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + Char c = *it; + if ((c >= '0' && c <= '9') || c == '{') { + it = detail::parse_width(it, end, specs_, width_ref_, ctx); + if (it == end) return it; + } + + if (*it == 'L') { + specs_.set_localized(); + ++it; + } + + end = detail::parse_chrono_format(it, end, + detail::tm_format_checker(has_timezone)); + // Replace the default format string only if the new spec is not empty. + if (end != it) fmt_ = {it, detail::to_unsigned(end - it)}; + return end; + } + + template + auto do_format(const std::tm& tm, FormatContext& ctx, + const Duration* subsecs) const -> decltype(ctx.out()) { + auto specs = specs_; + auto buf = basic_memory_buffer(); + auto out = basic_appender(buf); + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_, + ctx); + + auto loc_ref = specs.localized() ? ctx.locale() : detail::locale_ref(); + detail::get_locale loc(static_cast(loc_ref), loc_ref); + auto w = detail::tm_writer, Char, Duration>( + loc, out, tm, subsecs); + detail::parse_chrono_format(fmt_.begin(), fmt_.end(), w); + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return do_parse(ctx, detail::has_tm_gmtoff::value); + } + + template + auto format(const std::tm& tm, FormatContext& ctx) const + -> decltype(ctx.out()) { + return do_format(tm, ctx, nullptr); + } +}; + +// DEPRECATED! Reversed order of template parameters. +template +struct formatter, Char> : private formatter { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return this->do_parse(ctx, true); + } + + template + auto format(sys_time val, FormatContext& ctx) const + -> decltype(ctx.out()) { + std::tm tm = gmtime(val); + using period = typename Duration::period; + if (detail::const_check( + period::num == 1 && period::den == 1 && + !std::is_floating_point::value)) { + detail::set_tm_zone(tm, detail::utc()); + return formatter::format(tm, ctx); + } + Duration epoch = val.time_since_epoch(); + Duration subsecs = detail::duration_cast( + epoch - detail::duration_cast(epoch)); + if (subsecs.count() < 0) { + auto second = detail::duration_cast(std::chrono::seconds(1)); + if (tm.tm_sec != 0) { + --tm.tm_sec; + } else { + tm = gmtime(val - second); + detail::set_tm_zone(tm, detail::utc()); + } + subsecs += second; + } + return formatter::do_format(tm, ctx, &subsecs); + } +}; + +template +struct formatter, Char> + : formatter, Char> { + template + auto format(utc_time val, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter, Char>::format( + detail::utc_clock::to_sys(val), ctx); + } +}; + +template +struct formatter, Char> + : private formatter { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return this->do_parse(ctx, false); + } + + template + auto format(local_time val, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto time_since_epoch = val.time_since_epoch(); + auto seconds_since_epoch = + detail::duration_cast(time_since_epoch); + // Use gmtime to prevent time zone conversion since local_time has an + // unspecified time zone. + std::tm t = gmtime(seconds_since_epoch.count()); + using period = typename Duration::period; + if (period::num == 1 && period::den == 1 && + !std::is_floating_point::value) { + return formatter::format(t, ctx); + } + auto subsecs = + detail::duration_cast(time_since_epoch - seconds_since_epoch); + return formatter::do_format(t, ctx, &subsecs); + } +}; + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_CHRONO_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/color.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/color.h new file mode 100755 index 0000000000000000000000000000000000000000..638f15b43f380f26f95925b4191bb44d7c59c231 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/color.h @@ -0,0 +1,637 @@ +// Formatting library for C++ - color support +// +// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COLOR_H_ +#define FMT_COLOR_H_ + +#include "format.h" + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +enum class color : uint32_t { + alice_blue = 0xF0F8FF, // rgb(240,248,255) + antique_white = 0xFAEBD7, // rgb(250,235,215) + aqua = 0x00FFFF, // rgb(0,255,255) + aquamarine = 0x7FFFD4, // rgb(127,255,212) + azure = 0xF0FFFF, // rgb(240,255,255) + beige = 0xF5F5DC, // rgb(245,245,220) + bisque = 0xFFE4C4, // rgb(255,228,196) + black = 0x000000, // rgb(0,0,0) + blanched_almond = 0xFFEBCD, // rgb(255,235,205) + blue = 0x0000FF, // rgb(0,0,255) + blue_violet = 0x8A2BE2, // rgb(138,43,226) + brown = 0xA52A2A, // rgb(165,42,42) + burly_wood = 0xDEB887, // rgb(222,184,135) + cadet_blue = 0x5F9EA0, // rgb(95,158,160) + chartreuse = 0x7FFF00, // rgb(127,255,0) + chocolate = 0xD2691E, // rgb(210,105,30) + coral = 0xFF7F50, // rgb(255,127,80) + cornflower_blue = 0x6495ED, // rgb(100,149,237) + cornsilk = 0xFFF8DC, // rgb(255,248,220) + crimson = 0xDC143C, // rgb(220,20,60) + cyan = 0x00FFFF, // rgb(0,255,255) + dark_blue = 0x00008B, // rgb(0,0,139) + dark_cyan = 0x008B8B, // rgb(0,139,139) + dark_golden_rod = 0xB8860B, // rgb(184,134,11) + dark_gray = 0xA9A9A9, // rgb(169,169,169) + dark_green = 0x006400, // rgb(0,100,0) + dark_khaki = 0xBDB76B, // rgb(189,183,107) + dark_magenta = 0x8B008B, // rgb(139,0,139) + dark_olive_green = 0x556B2F, // rgb(85,107,47) + dark_orange = 0xFF8C00, // rgb(255,140,0) + dark_orchid = 0x9932CC, // rgb(153,50,204) + dark_red = 0x8B0000, // rgb(139,0,0) + dark_salmon = 0xE9967A, // rgb(233,150,122) + dark_sea_green = 0x8FBC8F, // rgb(143,188,143) + dark_slate_blue = 0x483D8B, // rgb(72,61,139) + dark_slate_gray = 0x2F4F4F, // rgb(47,79,79) + dark_turquoise = 0x00CED1, // rgb(0,206,209) + dark_violet = 0x9400D3, // rgb(148,0,211) + deep_pink = 0xFF1493, // rgb(255,20,147) + deep_sky_blue = 0x00BFFF, // rgb(0,191,255) + dim_gray = 0x696969, // rgb(105,105,105) + dodger_blue = 0x1E90FF, // rgb(30,144,255) + fire_brick = 0xB22222, // rgb(178,34,34) + floral_white = 0xFFFAF0, // rgb(255,250,240) + forest_green = 0x228B22, // rgb(34,139,34) + fuchsia = 0xFF00FF, // rgb(255,0,255) + gainsboro = 0xDCDCDC, // rgb(220,220,220) + ghost_white = 0xF8F8FF, // rgb(248,248,255) + gold = 0xFFD700, // rgb(255,215,0) + golden_rod = 0xDAA520, // rgb(218,165,32) + gray = 0x808080, // rgb(128,128,128) + green = 0x008000, // rgb(0,128,0) + green_yellow = 0xADFF2F, // rgb(173,255,47) + honey_dew = 0xF0FFF0, // rgb(240,255,240) + hot_pink = 0xFF69B4, // rgb(255,105,180) + indian_red = 0xCD5C5C, // rgb(205,92,92) + indigo = 0x4B0082, // rgb(75,0,130) + ivory = 0xFFFFF0, // rgb(255,255,240) + khaki = 0xF0E68C, // rgb(240,230,140) + lavender = 0xE6E6FA, // rgb(230,230,250) + lavender_blush = 0xFFF0F5, // rgb(255,240,245) + lawn_green = 0x7CFC00, // rgb(124,252,0) + lemon_chiffon = 0xFFFACD, // rgb(255,250,205) + light_blue = 0xADD8E6, // rgb(173,216,230) + light_coral = 0xF08080, // rgb(240,128,128) + light_cyan = 0xE0FFFF, // rgb(224,255,255) + light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210) + light_gray = 0xD3D3D3, // rgb(211,211,211) + light_green = 0x90EE90, // rgb(144,238,144) + light_pink = 0xFFB6C1, // rgb(255,182,193) + light_salmon = 0xFFA07A, // rgb(255,160,122) + light_sea_green = 0x20B2AA, // rgb(32,178,170) + light_sky_blue = 0x87CEFA, // rgb(135,206,250) + light_slate_gray = 0x778899, // rgb(119,136,153) + light_steel_blue = 0xB0C4DE, // rgb(176,196,222) + light_yellow = 0xFFFFE0, // rgb(255,255,224) + lime = 0x00FF00, // rgb(0,255,0) + lime_green = 0x32CD32, // rgb(50,205,50) + linen = 0xFAF0E6, // rgb(250,240,230) + magenta = 0xFF00FF, // rgb(255,0,255) + maroon = 0x800000, // rgb(128,0,0) + medium_aquamarine = 0x66CDAA, // rgb(102,205,170) + medium_blue = 0x0000CD, // rgb(0,0,205) + medium_orchid = 0xBA55D3, // rgb(186,85,211) + medium_purple = 0x9370DB, // rgb(147,112,219) + medium_sea_green = 0x3CB371, // rgb(60,179,113) + medium_slate_blue = 0x7B68EE, // rgb(123,104,238) + medium_spring_green = 0x00FA9A, // rgb(0,250,154) + medium_turquoise = 0x48D1CC, // rgb(72,209,204) + medium_violet_red = 0xC71585, // rgb(199,21,133) + midnight_blue = 0x191970, // rgb(25,25,112) + mint_cream = 0xF5FFFA, // rgb(245,255,250) + misty_rose = 0xFFE4E1, // rgb(255,228,225) + moccasin = 0xFFE4B5, // rgb(255,228,181) + navajo_white = 0xFFDEAD, // rgb(255,222,173) + navy = 0x000080, // rgb(0,0,128) + old_lace = 0xFDF5E6, // rgb(253,245,230) + olive = 0x808000, // rgb(128,128,0) + olive_drab = 0x6B8E23, // rgb(107,142,35) + orange = 0xFFA500, // rgb(255,165,0) + orange_red = 0xFF4500, // rgb(255,69,0) + orchid = 0xDA70D6, // rgb(218,112,214) + pale_golden_rod = 0xEEE8AA, // rgb(238,232,170) + pale_green = 0x98FB98, // rgb(152,251,152) + pale_turquoise = 0xAFEEEE, // rgb(175,238,238) + pale_violet_red = 0xDB7093, // rgb(219,112,147) + papaya_whip = 0xFFEFD5, // rgb(255,239,213) + peach_puff = 0xFFDAB9, // rgb(255,218,185) + peru = 0xCD853F, // rgb(205,133,63) + pink = 0xFFC0CB, // rgb(255,192,203) + plum = 0xDDA0DD, // rgb(221,160,221) + powder_blue = 0xB0E0E6, // rgb(176,224,230) + purple = 0x800080, // rgb(128,0,128) + rebecca_purple = 0x663399, // rgb(102,51,153) + red = 0xFF0000, // rgb(255,0,0) + rosy_brown = 0xBC8F8F, // rgb(188,143,143) + royal_blue = 0x4169E1, // rgb(65,105,225) + saddle_brown = 0x8B4513, // rgb(139,69,19) + salmon = 0xFA8072, // rgb(250,128,114) + sandy_brown = 0xF4A460, // rgb(244,164,96) + sea_green = 0x2E8B57, // rgb(46,139,87) + sea_shell = 0xFFF5EE, // rgb(255,245,238) + sienna = 0xA0522D, // rgb(160,82,45) + silver = 0xC0C0C0, // rgb(192,192,192) + sky_blue = 0x87CEEB, // rgb(135,206,235) + slate_blue = 0x6A5ACD, // rgb(106,90,205) + slate_gray = 0x708090, // rgb(112,128,144) + snow = 0xFFFAFA, // rgb(255,250,250) + spring_green = 0x00FF7F, // rgb(0,255,127) + steel_blue = 0x4682B4, // rgb(70,130,180) + tan = 0xD2B48C, // rgb(210,180,140) + teal = 0x008080, // rgb(0,128,128) + thistle = 0xD8BFD8, // rgb(216,191,216) + tomato = 0xFF6347, // rgb(255,99,71) + turquoise = 0x40E0D0, // rgb(64,224,208) + violet = 0xEE82EE, // rgb(238,130,238) + wheat = 0xF5DEB3, // rgb(245,222,179) + white = 0xFFFFFF, // rgb(255,255,255) + white_smoke = 0xF5F5F5, // rgb(245,245,245) + yellow = 0xFFFF00, // rgb(255,255,0) + yellow_green = 0x9ACD32 // rgb(154,205,50) +}; // enum class color + +enum class terminal_color : uint8_t { + black = 30, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + bright_black = 90, + bright_red, + bright_green, + bright_yellow, + bright_blue, + bright_magenta, + bright_cyan, + bright_white +}; + +enum class emphasis : uint8_t { + bold = 1, + faint = 1 << 1, + italic = 1 << 2, + underline = 1 << 3, + blink = 1 << 4, + reverse = 1 << 5, + conceal = 1 << 6, + strikethrough = 1 << 7, +}; + +// rgb is a struct for red, green and blue colors. +// Using the name "rgb" makes some editors show the color in a tooltip. +struct rgb { + constexpr rgb() : r(0), g(0), b(0) {} + constexpr rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {} + constexpr rgb(uint32_t hex) + : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {} + constexpr rgb(color hex) + : r((uint32_t(hex) >> 16) & 0xFF), + g((uint32_t(hex) >> 8) & 0xFF), + b(uint32_t(hex) & 0xFF) {} + uint8_t r; + uint8_t g; + uint8_t b; +}; + +namespace detail { + +// A bit-packed variant of an RGB color, a terminal color, or unset color. +// see text_style for the bit-packing scheme. +struct color_type { + constexpr color_type() noexcept = default; + constexpr color_type(color rgb_color) noexcept + : value_(static_cast(rgb_color) | (1 << 24)) {} + constexpr color_type(rgb rgb_color) noexcept + : color_type(static_cast( + (static_cast(rgb_color.r) << 16) | + (static_cast(rgb_color.g) << 8) | rgb_color.b)) {} + constexpr color_type(terminal_color term_color) noexcept + : value_(static_cast(term_color) | (3 << 24)) {} + + constexpr auto is_terminal_color() const noexcept -> bool { + return (value_ & (1 << 25)) != 0; + } + + constexpr auto value() const noexcept -> uint32_t { + return value_ & 0xFFFFFF; + } + + constexpr color_type(uint32_t value) noexcept : value_(value) {} + + uint32_t value_ = 0; +}; +} // namespace detail + +/// A text style consisting of foreground and background colors and emphasis. +class text_style { + // The information is packed as follows: + // ┌──┐ + // │ 0│─┐ + // │..│ ├── foreground color value + // │23│─┘ + // ├──┤ + // │24│─┬── discriminator for the above value. 00 if unset, 01 if it's + // │25│─┘ an RGB color, or 11 if it's a terminal color (10 is unused) + // ├──┤ + // │26│──── overflow bit, always zero (see below) + // ├──┤ + // │27│─┐ + // │..│ │ + // │50│ │ + // ├──┤ │ + // │51│ ├── background color (same format as the foreground color) + // │52│ │ + // ├──┤ │ + // │53│─┘ + // ├──┤ + // │54│─┐ + // │..│ ├── emphases + // │61│─┘ + // ├──┤ + // │62│─┬── unused + // │63│─┘ + // └──┘ + // The overflow bits are there to make operator|= efficient. + // When ORing, we must throw if, for either the foreground or background, + // one style specifies a terminal color and the other specifies any color + // (terminal or RGB); in other words, if one discriminator is 11 and the + // other is 11 or 01. + // + // We do that check by adding the styles. Consider what adding does to each + // possible pair of discriminators: + // 00 + 00 = 000 + // 01 + 00 = 001 + // 11 + 00 = 011 + // 01 + 01 = 010 + // 11 + 01 = 100 (!!) + // 11 + 11 = 110 (!!) + // In the last two cases, the ones we want to catch, the third bit——the + // overflow bit——is set. Bingo. + // + // We must take into account the possible carry bit from the bits + // before the discriminator. The only potentially problematic case is + // 11 + 00 = 011 (a carry bit would make it 100, not good!), but a carry + // bit is impossible in that case, because 00 (unset color) means the + // 24 bits that precede the discriminator are all zero. + // + // This test can be applied to both colors simultaneously. + + public: + FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept + : style_(static_cast(em) << 54) {} + + FMT_CONSTEXPR auto operator|=(text_style rhs) -> text_style& { + if (((style_ + rhs.style_) & ((1ULL << 26) | (1ULL << 53))) != 0) + report_error("can't OR a terminal color"); + style_ |= rhs.style_; + return *this; + } + + friend FMT_CONSTEXPR auto operator|(text_style lhs, text_style rhs) + -> text_style { + return lhs |= rhs; + } + + FMT_CONSTEXPR auto operator==(text_style rhs) const noexcept -> bool { + return style_ == rhs.style_; + } + + FMT_CONSTEXPR auto operator!=(text_style rhs) const noexcept -> bool { + return !(*this == rhs); + } + + FMT_CONSTEXPR auto has_foreground() const noexcept -> bool { + return (style_ & (1 << 24)) != 0; + } + FMT_CONSTEXPR auto has_background() const noexcept -> bool { + return (style_ & (1ULL << 51)) != 0; + } + FMT_CONSTEXPR auto has_emphasis() const noexcept -> bool { + return (style_ >> 54) != 0; + } + FMT_CONSTEXPR auto get_foreground() const noexcept -> detail::color_type { + FMT_ASSERT(has_foreground(), "no foreground specified for this style"); + return style_ & 0x3FFFFFF; + } + FMT_CONSTEXPR auto get_background() const noexcept -> detail::color_type { + FMT_ASSERT(has_background(), "no background specified for this style"); + return (style_ >> 27) & 0x3FFFFFF; + } + FMT_CONSTEXPR auto get_emphasis() const noexcept -> emphasis { + FMT_ASSERT(has_emphasis(), "no emphasis specified for this style"); + return static_cast(style_ >> 54); + } + + private: + FMT_CONSTEXPR text_style(uint64_t style) noexcept : style_(style) {} + + friend FMT_CONSTEXPR auto fg(detail::color_type foreground) noexcept + -> text_style; + + friend FMT_CONSTEXPR auto bg(detail::color_type background) noexcept + -> text_style; + + uint64_t style_ = 0; +}; + +/// Creates a text style from the foreground (text) color. +FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept + -> text_style { + return foreground.value_; +} + +/// Creates a text style from the background color. +FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept + -> text_style { + return static_cast(background.value_) << 27; +} + +FMT_CONSTEXPR inline auto operator|(emphasis lhs, emphasis rhs) noexcept + -> text_style { + return text_style(lhs) | rhs; +} + +namespace detail { + +template struct ansi_color_escape { + FMT_CONSTEXPR ansi_color_escape(color_type text_color, + const char* esc) noexcept { + // If we have a terminal color, we need to output another escape code + // sequence. + if (text_color.is_terminal_color()) { + bool is_background = esc == string_view("\x1b[48;2;"); + uint32_t value = text_color.value(); + // Background ASCII codes are the same as the foreground ones but with + // 10 more. + if (is_background) value += 10u; + + size_t index = 0; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + + if (value >= 100u) { + buffer[index++] = static_cast('1'); + value %= 100u; + } + buffer[index++] = static_cast('0' + value / 10u); + buffer[index++] = static_cast('0' + value % 10u); + + buffer[index++] = static_cast('m'); + buffer[index++] = static_cast('\0'); + return; + } + + for (int i = 0; i < 7; i++) { + buffer[i] = static_cast(esc[i]); + } + rgb color(text_color.value()); + to_esc(color.r, buffer + 7, ';'); + to_esc(color.g, buffer + 11, ';'); + to_esc(color.b, buffer + 15, 'm'); + buffer[19] = static_cast(0); + } + FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept { + uint8_t em_codes[num_emphases] = {}; + if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1; + if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2; + if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3; + if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4; + if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5; + if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7; + if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8; + if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9; + + size_t index = 0; + for (size_t i = 0; i < num_emphases; ++i) { + if (!em_codes[i]) continue; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + buffer[index++] = static_cast('0' + em_codes[i]); + buffer[index++] = static_cast('m'); + } + buffer[index++] = static_cast(0); + } + FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; } + + FMT_CONSTEXPR auto begin() const noexcept -> const Char* { return buffer; } + FMT_CONSTEXPR20 auto end() const noexcept -> const Char* { + return buffer + basic_string_view(buffer).size(); + } + + private: + static constexpr size_t num_emphases = 8; + Char buffer[7u + 3u * num_emphases + 1u]; + + static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out, + char delimiter) noexcept { + out[0] = static_cast('0' + c / 100); + out[1] = static_cast('0' + c / 10 % 10); + out[2] = static_cast('0' + c % 10); + out[3] = static_cast(delimiter); + } + static FMT_CONSTEXPR auto has_emphasis(emphasis em, emphasis mask) noexcept + -> bool { + return static_cast(em) & static_cast(mask); + } +}; + +template +FMT_CONSTEXPR auto make_foreground_color(color_type foreground) noexcept + -> ansi_color_escape { + return ansi_color_escape(foreground, "\x1b[38;2;"); +} + +template +FMT_CONSTEXPR auto make_background_color(color_type background) noexcept + -> ansi_color_escape { + return ansi_color_escape(background, "\x1b[48;2;"); +} + +template +FMT_CONSTEXPR auto make_emphasis(emphasis em) noexcept + -> ansi_color_escape { + return ansi_color_escape(em); +} + +template inline void reset_color(buffer& buffer) { + auto reset_color = string_view("\x1b[0m"); + buffer.append(reset_color.begin(), reset_color.end()); +} + +template struct styled_arg : view { + const T& value; + text_style style; + styled_arg(const T& v, text_style s) : value(v), style(s) {} +}; + +template +void vformat_to(buffer& buf, text_style ts, basic_string_view fmt, + basic_format_args> args) { + if (ts.has_emphasis()) { + auto emphasis = make_emphasis(ts.get_emphasis()); + buf.append(emphasis.begin(), emphasis.end()); + } + if (ts.has_foreground()) { + auto foreground = make_foreground_color(ts.get_foreground()); + buf.append(foreground.begin(), foreground.end()); + } + if (ts.has_background()) { + auto background = make_background_color(ts.get_background()); + buf.append(background.begin(), background.end()); + } + vformat_to(buf, fmt, args); + if (ts != text_style()) reset_color(buf); +} +} // namespace detail + +inline void vprint(FILE* f, text_style ts, string_view fmt, format_args args) { + auto buf = memory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + print(f, FMT_STRING("{}"), string_view(buf.begin(), buf.size())); +} + +/** + * Formats a string and prints it to the specified file stream using ANSI + * escape sequences to specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); + */ +template +void print(FILE* f, text_style ts, format_string fmt, T&&... args) { + vprint(f, ts, fmt.str, vargs{{args...}}); +} + +/** + * Formats a string and prints it to stdout using ANSI escape sequences to + * specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); + */ +template +void print(text_style ts, format_string fmt, T&&... args) { + return print(stdout, ts, fmt, std::forward(args)...); +} + +inline auto vformat(text_style ts, string_view fmt, format_args args) + -> std::string { + auto buf = memory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + return fmt::to_string(buf); +} + +/** + * Formats arguments and returns the result as a string using ANSI escape + * sequences to specify text formatting. + * + * **Example**: + * + * ``` + * #include + * std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), + * "The answer is {}", 42); + * ``` + */ +template +inline auto format(text_style ts, format_string fmt, T&&... args) + -> std::string { + return fmt::vformat(ts, fmt.str, vargs{{args...}}); +} + +/// Formats a string with the given text_style and writes the output to `out`. +template ::value)> +auto vformat_to(OutputIt out, text_style ts, string_view fmt, format_args args) + -> OutputIt { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, ts, fmt, args); + return detail::get_iterator(buf, out); +} + +/** + * Formats arguments with the given text style, writes the result to the output + * iterator `out` and returns the iterator past the end of the output range. + * + * **Example**: + * + * std::vector out; + * fmt::format_to(std::back_inserter(out), + * fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); + */ +template ::value)> +inline auto format_to(OutputIt out, text_style ts, format_string fmt, + T&&... args) -> OutputIt { + return vformat_to(out, ts, fmt.str, vargs{{args...}}); +} + +template +struct formatter, Char> : formatter { + template + auto format(const detail::styled_arg& arg, FormatContext& ctx) const + -> decltype(ctx.out()) { + const auto& ts = arg.style; + auto out = ctx.out(); + + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis(ts.get_emphasis()); + out = detail::copy(emphasis.begin(), emphasis.end(), out); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = + detail::make_foreground_color(ts.get_foreground()); + out = detail::copy(foreground.begin(), foreground.end(), out); + } + if (ts.has_background()) { + has_style = true; + auto background = + detail::make_background_color(ts.get_background()); + out = detail::copy(background.begin(), background.end(), out); + } + out = formatter::format(arg.value, ctx); + if (has_style) { + auto reset_color = string_view("\x1b[0m"); + out = detail::copy(reset_color.begin(), reset_color.end(), out); + } + return out; + } +}; + +/** + * Returns an argument that will be formatted using ANSI escape sequences, + * to be used in a formatting function. + * + * **Example**: + * + * fmt::print("Elapsed time: {0:.2f} seconds", + * fmt::styled(1.23, fmt::fg(fmt::color::green) | + * fmt::bg(fmt::color::blue))); + */ +template +FMT_CONSTEXPR auto styled(const T& value, text_style ts) + -> detail::styled_arg> { + return detail::styled_arg>{value, ts}; +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_COLOR_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/compile.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/compile.h new file mode 100755 index 0000000000000000000000000000000000000000..08d9427ff24faa4f68d74aecde04de27d7c21bfd --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/compile.h @@ -0,0 +1,539 @@ +// Formatting library for C++ - experimental format string compilation +// +// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COMPILE_H_ +#define FMT_COMPILE_H_ + +#ifndef FMT_MODULE +# include // std::back_inserter +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// A compile-time string which is compiled into fast formatting code. +FMT_EXPORT class compiled_string {}; + +template +struct is_compiled_string : std::is_base_of {}; + +namespace detail { + +/** + * Converts a string literal `s` into a format string that will be parsed at + * compile time and converted into efficient formatting code. Requires C++17 + * `constexpr if` compiler support. + * + * **Example**: + * + * // Converts 42 into std::string using the most efficient method and no + * // runtime format string processing. + * std::string s = fmt::format(FMT_COMPILE("{}"), 42); + */ +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string) +#else +# define FMT_COMPILE(s) FMT_STRING(s) +#endif + +template +auto first(const T& value, const Tail&...) -> const T& { + return value; +} + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +template struct type_list {}; + +// Returns a reference to the argument at index N from [first, rest...]. +template +constexpr const auto& get([[maybe_unused]] const T& first, + [[maybe_unused]] const Args&... rest) { + static_assert(N < 1 + sizeof...(Args), "index is out of bounds"); + if constexpr (N == 0) + return first; + else + return detail::get(rest...); +} + +# if FMT_USE_NONTYPE_TEMPLATE_ARGS +template +constexpr auto get_arg_index_by_name(basic_string_view name) -> int { + if constexpr (is_static_named_arg()) { + if (name == T::name) return N; + } + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name(name); + (void)name; // Workaround an MSVC bug about "unused" parameter. + return -1; +} +# endif + +template +FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view name) -> int { +# if FMT_USE_NONTYPE_TEMPLATE_ARGS + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<0, Args...>(name); +# endif + (void)name; + return -1; +} + +template +constexpr int get_arg_index_by_name(basic_string_view name, + type_list) { + return get_arg_index_by_name(name); +} + +template struct get_type_impl; + +template struct get_type_impl> { + using type = + remove_cvref_t(std::declval()...))>; +}; + +template +using get_type = typename get_type_impl::type; + +template struct is_compiled_format : std::false_type {}; + +template struct text { + basic_string_view data; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write(out, data); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr text make_text(basic_string_view s, size_t pos, + size_t size) { + return {{&s[pos], size}}; +} + +template struct code_unit { + Char value; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + *out++ = value; + return out; + } +}; + +// This ensures that the argument type is convertible to `const T&`. +template +constexpr const T& get_arg_checked(const Args&... args) { + const auto& arg = detail::get(args...); + if constexpr (detail::is_named_arg>()) { + return arg.value; + } else { + return arg; + } +} + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N. +template struct field { + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + const T& arg = get_arg_checked(args...); + if constexpr (std::is_convertible>::value) { + auto s = basic_string_view(arg); + return copy(s.begin(), s.end(), out); + } else { + return write(out, arg); + } + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument with name. +template struct runtime_named_field { + using char_type = Char; + basic_string_view name; + + template + constexpr static bool try_format_argument( + OutputIt& out, + // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9 + [[maybe_unused]] basic_string_view arg_name, const T& arg) { + if constexpr (is_named_arg::type>::value) { + if (arg_name == arg.name) { + out = write(out, arg.value); + return true; + } + } + return false; + } + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + bool found = (try_format_argument(out, name, args) || ...); + if (!found) { + FMT_THROW(format_error("argument with specified name is not found")); + } + return out; + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N and has format specifiers. +template struct spec_field { + using char_type = Char; + formatter fmt; + + template + constexpr FMT_INLINE OutputIt format(OutputIt out, + const Args&... args) const { + const auto& vargs = + fmt::make_format_args>(args...); + basic_format_context ctx(out, vargs); + return fmt.format(get_arg_checked(args...), ctx); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template struct concat { + L lhs; + R rhs; + using char_type = typename L::char_type; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + out = lhs.format(out, args...); + return rhs.format(out, args...); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr concat make_concat(L lhs, R rhs) { + return {lhs, rhs}; +} + +struct unknown_format {}; + +template +constexpr size_t parse_text(basic_string_view str, size_t pos) { + for (size_t size = str.size(); pos != size; ++pos) { + if (str[pos] == '{' || str[pos] == '}') break; + } + return pos; +} + +template +constexpr auto compile_format_string(S fmt); + +template +constexpr auto parse_tail(T head, S fmt) { + if constexpr (POS != basic_string_view(fmt).size()) { + constexpr auto tail = compile_format_string(fmt); + if constexpr (std::is_same, + unknown_format>()) + return tail; + else + return make_concat(head, tail); + } else { + return head; + } +} + +template struct parse_specs_result { + formatter fmt; + size_t end; + int next_arg_id; +}; + +enum { manual_indexing_id = -1 }; + +template +constexpr parse_specs_result parse_specs(basic_string_view str, + size_t pos, int next_arg_id) { + str.remove_prefix(pos); + auto ctx = + compile_parse_context(str, max_value(), nullptr, next_arg_id); + auto f = formatter(); + auto end = f.parse(ctx); + return {f, pos + fmt::detail::to_unsigned(end - str.data()), + next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; +} + +template struct arg_id_handler { + arg_id_kind kind; + arg_ref arg_id; + + constexpr int on_auto() { + FMT_ASSERT(false, "handler cannot be used with automatic indexing"); + return 0; + } + constexpr int on_index(int id) { + kind = arg_id_kind::index; + arg_id = arg_ref(id); + return 0; + } + constexpr int on_name(basic_string_view id) { + kind = arg_id_kind::name; + arg_id = arg_ref(id); + return 0; + } +}; + +template struct parse_arg_id_result { + arg_id_kind kind; + arg_ref arg_id; + const Char* arg_id_end; +}; + +template +constexpr auto parse_arg_id(const Char* begin, const Char* end) { + auto handler = arg_id_handler{arg_id_kind::none, arg_ref{}}; + auto arg_id_end = parse_arg_id(begin, end, handler); + return parse_arg_id_result{handler.kind, handler.arg_id, arg_id_end}; +} + +template struct field_type { + using type = remove_cvref_t; +}; + +template +struct field_type::value>> { + using type = remove_cvref_t; +}; + +template +constexpr auto parse_replacement_field_then_tail(S fmt) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(fmt); + constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); + if constexpr (c == '}') { + return parse_tail( + field::type, ARG_INDEX>(), fmt); + } else if constexpr (c != ':') { + FMT_THROW(format_error("expected ':'")); + } else { + constexpr auto result = parse_specs::type>( + str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); + if constexpr (result.end >= str.size() || str[result.end] != '}') { + FMT_THROW(format_error("expected '}'")); + return 0; + } else { + return parse_tail( + spec_field::type, ARG_INDEX>{ + result.fmt}, + fmt); + } + } +} + +// Compiles a non-empty format string and returns the compiled representation +// or unknown_format() on unrecognized input. +template +constexpr auto compile_format_string(S fmt) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(fmt); + if constexpr (str[POS] == '{') { + if constexpr (POS + 1 == str.size()) + FMT_THROW(format_error("unmatched '{' in format string")); + if constexpr (str[POS + 1] == '{') { + return parse_tail(make_text(str, POS, 1), fmt); + } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { + static_assert(ID != manual_indexing_id, + "cannot switch from manual to automatic argument indexing"); + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail, Args, + POS + 1, ID, next_id>(fmt); + } else { + constexpr auto arg_id_result = + parse_arg_id(str.data() + POS + 1, str.data() + str.size()); + constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data(); + constexpr char_type c = + arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type(); + static_assert(c == '}' || c == ':', "missing '}' in format string"); + if constexpr (arg_id_result.kind == arg_id_kind::index) { + static_assert( + ID == manual_indexing_id || ID == 0, + "cannot switch from automatic to manual argument indexing"); + constexpr auto arg_index = arg_id_result.arg_id.index; + return parse_replacement_field_then_tail, + Args, arg_id_end_pos, + arg_index, manual_indexing_id>( + fmt); + } else if constexpr (arg_id_result.kind == arg_id_kind::name) { + constexpr auto arg_index = + get_arg_index_by_name(arg_id_result.arg_id.name, Args{}); + if constexpr (arg_index >= 0) { + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail< + decltype(get_type::value), Args, arg_id_end_pos, + arg_index, next_id>(fmt); + } else if constexpr (c == '}') { + return parse_tail( + runtime_named_field{arg_id_result.arg_id.name}, fmt); + } else if constexpr (c == ':') { + return unknown_format(); // no type info for specs parsing + } + } + } + } else if constexpr (str[POS] == '}') { + if constexpr (POS + 1 == str.size()) + FMT_THROW(format_error("unmatched '}' in format string")); + return parse_tail(make_text(str, POS, 1), fmt); + } else { + constexpr auto end = parse_text(str, POS + 1); + if constexpr (end - POS > 1) { + return parse_tail(make_text(str, POS, end - POS), fmt); + } else { + return parse_tail(code_unit{str[POS]}, fmt); + } + } +} + +template ::value)> +constexpr auto compile(S fmt) { + constexpr auto str = basic_string_view(fmt); + if constexpr (str.size() == 0) { + return detail::make_text(str, 0, 0); + } else { + constexpr auto result = + detail::compile_format_string, 0, 0>(fmt); + return result; + } +} +#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +} // namespace detail + +FMT_BEGIN_EXPORT + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) + +template ::value)> +FMT_INLINE std::basic_string format(const CompiledFormat& cf, + const Args&... args) { + auto s = std::basic_string(); + cf.format(std::back_inserter(s), args...); + return s; +} + +template ::value)> +constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, + const Args&... args) { + return cf.format(out, args...); +} + +template ::value)> +FMT_INLINE std::basic_string format(const S&, + Args&&... args) { + if constexpr (std::is_same::value) { + constexpr auto str = basic_string_view(S()); + if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { + const auto& first = detail::first(args...); + if constexpr (detail::is_named_arg< + remove_cvref_t>::value) { + return fmt::to_string(first.value); + } else { + return fmt::to_string(first); + } + } + } + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format( + static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format(compiled, std::forward(args)...); + } +} + +template ::value)> +FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format_to( + out, static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format_to(out, compiled, std::forward(args)...); + } +} +#endif + +template ::value)> +auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + fmt::format_to(std::back_inserter(buf), fmt, std::forward(args)...); + return {buf.out(), buf.count()}; +} + +template ::value)> +FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) + -> size_t { + auto buf = detail::counting_buffer<>(); + fmt::format_to(appender(buf), fmt, args...); + return buf.count(); +} + +template ::value)> +void print(std::FILE* f, const S& fmt, const Args&... args) { + auto buf = memory_buffer(); + fmt::format_to(appender(buf), fmt, args...); + detail::print(f, {buf.data(), buf.size()}); +} + +template ::value)> +void print(const S& fmt, const Args&... args) { + print(stdout, fmt, args...); +} + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +inline namespace literals { +template constexpr auto operator""_cf() { + return FMT_COMPILE(Str.data); +} +} // namespace literals +#endif + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_COMPILE_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/core.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/core.h new file mode 100755 index 0000000000000000000000000000000000000000..8ca735f0c00498a19b7bcc44493b1417faf4fb8c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/core.h @@ -0,0 +1,5 @@ +// This file is only provided for compatibility and may be removed in future +// versions. Use fmt/base.h if you don't need fmt::format and fmt/format.h +// otherwise. + +#include "format.h" diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/fmt.license.rst b/vendor/opensource/log_lib/spdlog/fmt/bundled/fmt.license.rst new file mode 100755 index 0000000000000000000000000000000000000000..1cd1ef92696b65b2ecb0e560e622f0a0e869dcf3 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/fmt.license.rst @@ -0,0 +1,27 @@ +Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/format-inl.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/format-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..bfe440c6364b288403d743a623e2ae01dd2fd114 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/format-inl.h @@ -0,0 +1,1948 @@ +// Formatting library for C++ - implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_FORMAT_INL_H_ +#define FMT_FORMAT_INL_H_ + +#ifndef FMT_MODULE +# include +# include // errno +# include +# include +# include +#endif + +#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE) +# include // _isatty +#endif + +#include "format.h" + +#if FMT_USE_LOCALE +# include +#endif + +#ifndef FMT_FUNC +# define FMT_FUNC +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_FUNC void assert_fail(const char* file, int line, const char* message) { + // Use unchecked std::fprintf to avoid triggering another assertion when + // writing to stderr fails. + fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); + abort(); +} + +FMT_FUNC void format_error_code(detail::buffer& out, int error_code, + string_view message) noexcept { + // Report error code making sure that the output fits into + // inline_buffer_size to avoid dynamic f_memory allocation and potential + // bad_alloc. + out.try_resize(0); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + auto abs_value = static_cast>(error_code); + if (detail::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); + auto it = appender(out); + if (message.size() <= inline_buffer_size - error_code_size) + fmt::format_to(it, FMT_STRING("{}{}"), message, SEP); + fmt::format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); + FMT_ASSERT(out.size() <= inline_buffer_size, ""); +} + +FMT_FUNC void do_report_error(format_func func, int error_code, + const char* message) noexcept { + memory_buffer full_message; + func(full_message, error_code, message); + // Don't use fwrite_all because the latter may throw. + if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0) + std::fputc('\n', stderr); +} + +// A wrapper around fwrite that throws on error. +inline void fwrite_all(const void* ptr, size_t count, FILE* stream) { + size_t written = std::fwrite(ptr, 1, count, stream); + if (written < count) + FMT_THROW(system_error(errno, FMT_STRING("cannot write to file"))); +} + +#if FMT_USE_LOCALE +using std::locale; +using std::numpunct; +using std::use_facet; + +template +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same::value, ""); +} +#else +struct locale {}; +template struct numpunct { + auto grouping() const -> std::string { return "\03"; } + auto thousands_sep() const -> Char { return ','; } + auto decimal_point() const -> Char { return '.'; } +}; +template Facet use_facet(locale) { return {}; } +#endif // FMT_USE_LOCALE + +template auto locale_ref::get() const -> Locale { + static_assert(std::is_same::value, ""); +#if FMT_USE_LOCALE + if (locale_) return *static_cast(locale_); +#endif + return locale(); +} + +template +FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result { + auto&& facet = use_facet>(loc.get()); + auto grouping = facet.grouping(); + auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep(); + return {std::move(grouping), thousands_sep}; +} +template +FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char { + return use_facet>(loc.get()).decimal_point(); +} + +#if FMT_USE_LOCALE +FMT_FUNC auto write_loc(appender out, loc_value value, + const format_specs& specs, locale_ref loc) -> bool { + auto locale = loc.get(); + // We cannot use the num_put facet because it may produce output in + // a wrong encoding. + using facet = format_facet; + if (std::has_facet(locale)) + return use_facet(locale).put(out, value, specs); + return facet(locale).put(out, value, specs); +} +#endif +} // namespace detail + +FMT_FUNC void report_error(const char* message) { +#if FMT_USE_EXCEPTIONS + // Use FMT_THROW instead of throw to avoid bogus unreachable code warnings + // from MSVC. + FMT_THROW(format_error(message)); +#else + fputs(message, stderr); + abort(); +#endif +} + +template typename Locale::id format_facet::id; + +template format_facet::format_facet(Locale& loc) { + auto& np = detail::use_facet>(loc); + grouping_ = np.grouping(); + if (!grouping_.empty()) separator_ = std::string(1, np.thousands_sep()); +} + +#if FMT_USE_LOCALE +template <> +FMT_API FMT_FUNC auto format_facet::do_put( + appender out, loc_value val, const format_specs& specs) const -> bool { + return val.visit( + detail::loc_writer<>{out, specs, separator_, grouping_, decimal_point_}); +} +#endif + +FMT_FUNC auto vsystem_error(int error_code, string_view fmt, format_args args) + -> std::system_error { + auto ec = std::error_code(error_code, std::generic_category()); + return std::system_error(ec, vformat(fmt, args)); +} + +namespace detail { + +template +inline auto operator==(basic_fp x, basic_fp y) -> bool { + return x.f == y.f && x.e == y.e; +} + +// Compilers should be able to optimize this into the ror instruction. +FMT_CONSTEXPR inline auto rotr(uint32_t n, uint32_t r) noexcept -> uint32_t { + r &= 31; + return (n >> r) | (n << (32 - r)); +} +FMT_CONSTEXPR inline auto rotr(uint64_t n, uint32_t r) noexcept -> uint64_t { + r &= 63; + return (n >> r) | (n << (64 - r)); +} + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes upper 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline auto umul96_upper64(uint32_t x, uint64_t y) noexcept -> uint64_t { + return umul128_upper64(static_cast(x) << 32, y); +} + +// Computes lower 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline auto umul192_lower128(uint64_t x, uint128_fallback y) noexcept + -> uint128_fallback { + uint64_t high = x * y.high(); + uint128_fallback high_low = umul128(x, y.low()); + return {high + high_low.high(), high_low.low()}; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline auto umul96_lower64(uint32_t x, uint64_t y) noexcept -> uint64_t { + return x * y; +} + +// Various fast log computations. +inline auto floor_log10_pow2_minus_log10_4_over_3(int e) noexcept -> int { + FMT_ASSERT(e <= 2936 && e >= -2985, "too large exponent"); + return (e * 631305 - 261663) >> 21; +} + +FMT_INLINE_VARIABLE constexpr struct div_small_pow10_infos_struct { + uint32_t divisor; + int shift_amount; +} div_small_pow10_infos[] = {{10, 16}, {100, 16}}; + +// Replaces n by floor(n / pow(10, N)) returning true if and only if n is +// divisible by pow(10, N). +// Precondition: n <= pow(10, N + 1). +template +auto check_divisibility_and_divide_by_pow10(uint32_t& n) noexcept -> bool { + // The numbers below are chosen such that: + // 1. floor(n/d) = floor(nm / 2^k) where d=10 or d=100, + // 2. nm mod 2^k < m if and only if n is divisible by d, + // where m is magic_number, k is shift_amount + // and d is divisor. + // + // Item 1 is a common technique of replacing division by a constant with + // multiplication, see e.g. "Division by Invariant Integers Using + // Multiplication" by Granlund and Montgomery (1994). magic_number (m) is set + // to ceil(2^k/d) for large enough k. + // The idea for item 2 originates from Schubfach. + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + n *= magic_number; + const uint32_t comparison_mask = (1u << info.shift_amount) - 1; + bool result = (n & comparison_mask) < magic_number; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template auto small_division_by_pow10(uint32_t n) noexcept -> uint32_t { + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + return (n * magic_number) >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline auto divide_by_10_to_kappa_plus_1(uint32_t n) noexcept -> uint32_t { + // 1374389535 = ceil(2^37/100) + return static_cast((static_cast(n) * 1374389535) >> 37); +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline auto divide_by_10_to_kappa_plus_1(uint64_t n) noexcept -> uint64_t { + // 2361183241434822607 = ceil(2^(64+7)/1000) + return umul128_upper64(n, 2361183241434822607ull) >> 7; +} + +// Various subroutines using pow10 cache +template struct cache_accessor; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint64_t; + + static auto get_cached_power(int k) noexcept -> uint64_t { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + static constexpr const uint64_t pow10_significands[] = { + 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, + 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb, + 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28, + 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, + 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, + 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810, + 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, + 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, + 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, + 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000, + 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, + 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, + 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, + 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000, + 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, + 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, + 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0, + 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985, + 0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297, + 0x9dc5ada82b70b59e, 0xc5371912364ce306, 0xf684df56c3e01bc7, + 0x9a130b963a6c115d, 0xc097ce7bc90715b4, 0xf0bdc21abb48db21, + 0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe, + 0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a, + 0x8f7e32ce7bea5c70, 0xb35dbf821ae4f38c, 0xe0352f62a19e306f}; + return pow10_significands[k - float_info::min_k]; + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static auto compute_mul(carrier_uint u, + const cache_entry_type& cache) noexcept + -> compute_mul_result { + auto r = umul96_upper64(u, cache); + return {static_cast(r >> 32), + static_cast(r) == 0}; + } + + static auto compute_delta(const cache_entry_type& cache, int beta) noexcept + -> uint32_t { + return static_cast(cache >> (64 - 1 - beta)); + } + + static auto compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta) noexcept + -> compute_mul_parity_result { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul96_lower64(two_f, cache); + return {((r >> (64 - beta)) & 1) != 0, + static_cast(r >> (32 - beta)) == 0}; + } + + static auto compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return static_cast( + (cache - (cache >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static auto compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return static_cast( + (cache + (cache >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static auto compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (static_cast( + cache >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint128_fallback; + + static auto get_cached_power(int k) noexcept -> uint128_fallback { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + + static constexpr const uint128_fallback pow10_significands[] = { +#if FMT_USE_FULL_CACHE_DRAGONBOX + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0x9faacf3df73609b1, 0x77b191618c54e9ad}, + {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, + {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e}, + {0x9becce62836ac577, 0x4ee367f9430aec33}, + {0xc2e801fb244576d5, 0x229c41f793cda740}, + {0xf3a20279ed56d48a, 0x6b43527578c11110}, + {0x9845418c345644d6, 0x830a13896b78aaaa}, + {0xbe5691ef416bd60c, 0x23cc986bc656d554}, + {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9}, + {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, + {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54}, + {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, + {0x91376c36d99995be, 0x23100809b9c21fa2}, + {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, + {0xe2e69915b3fff9f9, 0x16c90c8f323f516d}, + {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, + {0xb1442798f49ffb4a, 0x99cd11cfdf41779d}, + {0xdd95317f31c7fa1d, 0x40405643d711d584}, + {0x8a7d3eef7f1cfc52, 0x482835ea666b2573}, + {0xad1c8eab5ee43b66, 0xda3243650005eed0}, + {0xd863b256369d4a40, 0x90bed43e40076a83}, + {0x873e4f75e2224e68, 0x5a7744a6e804a292}, + {0xa90de3535aaae202, 0x711515d0a205cb37}, + {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, + {0x8412d9991ed58091, 0xe858790afe9486c3}, + {0xa5178fff668ae0b6, 0x626e974dbe39a873}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, + {0xa139029f6a239f72, 0x1c1fffc1ebc44e81}, + {0xc987434744ac874e, 0xa327ffb266b56221}, + {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9}, + {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, + {0xc4ce17b399107c22, 0xcb550fb4384d21d4}, + {0xf6019da07f549b2b, 0x7e2a53a146606a49}, + {0x99c102844f94e0fb, 0x2eda7444cbfc426e}, + {0xc0314325637a1939, 0xfa911155fefb5309}, + {0xf03d93eebc589f88, 0x793555ab7eba27cb}, + {0x96267c7535b763b5, 0x4bc1558b2f3458df}, + {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17}, + {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, + {0x92a1958a7675175f, 0x0bfacd89ec191eca}, + {0xb749faed14125d36, 0xcef980ec671f667c}, + {0xe51c79a85916f484, 0x82b7e12780e7401b}, + {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, + {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16}, + {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, + {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1}, + {0xaecc49914078536d, 0x58fae9f773886e19}, + {0xda7f5bf590966848, 0xaf39a475506a899f}, + {0x888f99797a5e012d, 0x6d8406c952429604}, + {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84}, + {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, + {0x855c3be0a17fcd26, 0x5cf2eea09a550680}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0xd0601d8efc57b08b, 0xf13b94daf124da27}, + {0x823c12795db6ce57, 0x76c53d08d6b70859}, + {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f}, + {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, + {0xfe5d54150b090b02, 0xd3f93b35435d7c4d}, + {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, + {0xc6b8e9b0709f109a, 0x359ab6419ca1091c}, + {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, + {0x9b407691d7fc44f8, 0x79e0de63425dcf1e}, + {0xc21094364dfb5636, 0x985915fc12f542e5}, + {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e}, + {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, + {0xbd8430bd08277231, 0x50c6ff782a838354}, + {0xece53cec4a314ebd, 0xa4f8bf5635246429}, + {0x940f4613ae5ed136, 0x871b7795e136be9a}, + {0xb913179899f68584, 0x28e2557b59846e40}, + {0xe757dd7ec07426e5, 0x331aeada2fe589d0}, + {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, + {0xb4bca50b065abe63, 0x0fed077a756b53aa}, + {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, + {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d}, + {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, + {0xdca04777f541c567, 0xecf0d7a0fc5583a1}, + {0x89e42caaf9491b60, 0xf41686c49db57245}, + {0xac5d37d5b79b6239, 0x311c2875c522ced6}, + {0xd77485cb25823ac7, 0x7d633293366b828c}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, + {0xd267caa862a12d66, 0xd072df63c324fd7c}, + {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, + {0xa46116538d0deb78, 0x52d9be85f074e609}, + {0xcd795be870516656, 0x67902e276c921f8c}, + {0x806bd9714632dff6, 0x00ba1cd8a3db53b7}, + {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, + {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce}, + {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, + {0x9cc3a6eec6311a63, 0xcbe3303674053bb1}, + {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, + {0xf4f1b4d515acb93b, 0xee92fb5515482d45}, + {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, + {0xbf5cd54678eef0b6, 0xd262d45a78a0635e}, + {0xef340a98172aace4, 0x86fb897116c87c35}, + {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1}, + {0xbae0a846d2195712, 0x8974836059cca10a}, + {0xe998d258869facd7, 0x2bd1a438703fc94c}, + {0x91ff83775423cc06, 0x7b6306a34627ddd0}, + {0xb67f6455292cbf08, 0x1a3bc84c17b1d543}, + {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, + {0x8e938662882af53e, 0x547eb47b7282ee9d}, + {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, + {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5}, + {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, + {0xae0b158b4738705e, 0x9624ab50b148d446}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7}, + {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, + {0xd47487cc8470652b, 0x7647c32000696720}, + {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, + {0xa5fb0a17c777cf09, 0xf468107100525891}, + {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, + {0x81ac1fe293d599bf, 0xc6f14cd848405531}, + {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, + {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d}, + {0xfd442e4688bd304a, 0x908f4a166d1da664}, + {0x9e4a9cec15763e2e, 0x9a598e4e043287ff}, + {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, + {0xf7549530e188c128, 0xd12bee59e68ef47d}, + {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, + {0xc13a148e3032d6e7, 0xe36a52363c1faf02}, + {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, + {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba}, + {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, + {0xebdf661791d60f56, 0x111b495b3464ad22}, + {0x936b9fcebb25c995, 0xcab10dd900beec35}, + {0xb84687c269ef3bfb, 0x3d5d514f40eea743}, + {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, + {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac}, + {0xb3f4e093db73a093, 0x59ed216765690f57}, + {0xe0f218b8d25088b8, 0x306869c13ec3532d}, + {0x8c974f7383725573, 0x1e414218c73a13fc}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, + {0x894bc396ce5da772, 0x6b8bba8c328eb784}, + {0xab9eb47c81f5114f, 0x066ea92f3f326565}, + {0xd686619ba27255a2, 0xc80a537b0efefebe}, + {0x8613fd0145877585, 0xbd06742ce95f5f37}, + {0xa798fc4196e952e7, 0x2c48113823b73705}, + {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, + {0x82ef85133de648c4, 0x9a984d73dbe722fc}, + {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, + {0xcc963fee10b7d1b3, 0x318df905079926a9}, + {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, + {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634}, + {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, + {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1}, + {0x9c1661a651213e2d, 0x06bea10ca65c084f}, + {0xc31bfa0fe5698db8, 0x486e494fcff30a63}, + {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, + {0x986ddb5c6b3a76b7, 0xf89629465a75e01d}, + {0xbe89523386091465, 0xf6bbb397f1135824}, + {0xee2ba6c0678b597f, 0x746aa07ded582e2d}, + {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, + {0xba121a4650e4ddeb, 0x92f34d62616ce414}, + {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, + {0x915e2486ef32cd60, 0x0ace1474dc1d122f}, + {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, + {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3}, + {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, + {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c}, + {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, + {0xd89d64d57a607744, 0xe871c7bf077ba8b8}, + {0x87625f056c7c4a8b, 0x11471cd764ad4973}, + {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0}, + {0xd389b47879823479, 0x4aff1d108d4ec2c4}, + {0x843610cb4bf160cb, 0xcedf722a585139bb}, + {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, + {0xce947a3da6a9273e, 0x733d226229feea33}, + {0x811ccc668829b887, 0x0806357d5a3f5260}, + {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8}, + {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, + {0xfc2c3f3841f17c67, 0xbbac2078d443ace3}, + {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, + {0xc5029163f384a931, 0x0a9e795e65d4df12}, + {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, + {0x99ea0196163fa42e, 0x504bced1bf8e4e46}, + {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, + {0xf07da27a82c37088, 0x5d767327bb4e5a4d}, + {0x964e858c91ba2655, 0x3a6a07f8d510f870}, + {0xbbe226efb628afea, 0x890489f70a55368c}, + {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, + {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e}, + {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, + {0xb32df8e9f3546564, 0x47939822dc96abfa}, + {0xdff9772470297ebd, 0x59787e2b93bc56f8}, + {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b}, + {0xaefae51477a06b03, 0xede622920b6b23f2}, + {0xdab99e59958885c4, 0xe95fab368e45ecee}, + {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, + {0xaae103b5fcd2a881, 0xd652bdc29f26a11a}, + {0xd59944a37c0752a2, 0x4be76d3346f04960}, + {0x857fcae62d8493a5, 0x6f70a4400c562ddc}, + {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, + {0xd097ad07a71f26b2, 0x7e2000a41346a7a8}, + {0x825ecc24c873782f, 0x8ed400668c0c28c9}, + {0xa2f67f2dfa90563b, 0x728900802f0f32fb}, + {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, + {0xfea126b7d78186bc, 0xe2f610c84987bfa9}, + {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, + {0xc6ede63fa05d3143, 0x91503d1c79720dbc}, + {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, + {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb}, + {0xc24452da229b021b, 0xfbe85badce996169}, + {0xf2d56790ab41c2a2, 0xfae27299423fb9c4}, + {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, + {0xbdb6b8e905cb600f, 0x5400e987bbc1c921}, + {0xed246723473e3813, 0x290123e9aab23b69}, + {0x9436c0760c86e30b, 0xf9a0b6720aaf6522}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0xe7958cb87392c2c2, 0xb60b1d1230b20e05}, + {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, + {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4}, + {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, + {0x8d590723948a535f, 0x579c487e5a38ad0f}, + {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, + {0xdcdb1b2798182244, 0xf8e431456cf88e66}, + {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, + {0xac8b2d36eed2dac5, 0xe272467e3d222f40}, + {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, + {0x86ccbb52ea94baea, 0x98e947129fc2b4ea}, + {0xa87fea27a539e9a5, 0x3f2398d747b36225}, + {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae}, + {0x83a3eeeef9153e89, 0x1953cf68300424ad}, + {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8}, + {0xcdb02555653131b6, 0x3792f412cb06794e}, + {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1}, + {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, + {0xc8de047564d20a8b, 0xf245825a5a445276}, + {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, + {0x9ced737bb6c4183d, 0x55464dd69685606c}, + {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, + {0xf53304714d9265df, 0xd53dd99f4b3066a9}, + {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, + {0xbf8fdb78849a5f96, 0xde98520472bdd034}, + {0xef73d256a5c0f77c, 0x963e66858f6d4441}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xbb127c53b17ec159, 0x5560c018580d5d53}, + {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7}, + {0x9226712162ab070d, 0xcab3961304ca70e9}, + {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23}, + {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, + {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243}, + {0xb267ed1940f1c61c, 0x55f038b237591ed4}, + {0xdf01e85f912e37a3, 0x6b6c46dec52f6689}, + {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, + {0xae397d8aa96c1b77, 0xabec975e0a0d081b}, + {0xd9c7dced53c72255, 0x96e7bd358c904a22}, + {0x881cea14545c7575, 0x7e50d64177da2e55}, + {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, + {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865}, + {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, + {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f}, + {0xcfb11ead453994ba, 0x67de18eda5814af3}, + {0x81ceb32c4b43fcf4, 0x80eacf948770ced8}, + {0xa2425ff75e14fc31, 0xa1258379a94d028e}, + {0xcad2f7f5359a3b3e, 0x096ee45813a04331}, + {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, + {0x9e74d1b791e07e48, 0x775ea264cf55347e}, + {0xc612062576589dda, 0x95364afe032a819e}, + {0xf79687aed3eec551, 0x3a83ddbd83f52205}, + {0x9abe14cd44753b52, 0xc4926a9672793543}, + {0xc16d9a0095928a27, 0x75b7053c0f178294}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0x971da05074da7bee, 0xd3f6fc16ebca5e04}, + {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, + {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6}, + {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, + {0xb877aa3236a4b449, 0x09befeb9fad487c3}, + {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, + {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11}, + {0xb424dc35095cd80f, 0x538484c19ef38c95}, + {0xe12e13424bb40e13, 0x2865a5f206b06fba}, + {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, + {0xafebff0bcb24aafe, 0xf78f69a51539d749}, + {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, + {0x89705f4136b4a597, 0x31680a88f8953031}, + {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, + {0xd6bf94d5e57a42bc, 0x3d32907604691b4d}, + {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, + {0xa7c5ac471b478423, 0x0fcf80dc33721d54}, + {0xd1b71758e219652b, 0xd3c36113404ea4a9}, + {0x83126e978d4fdf3b, 0x645a1cac083126ea}, + {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, + {0xcccccccccccccccc, 0xcccccccccccccccd}, + {0x8000000000000000, 0x0000000000000000}, + {0xa000000000000000, 0x0000000000000000}, + {0xc800000000000000, 0x0000000000000000}, + {0xfa00000000000000, 0x0000000000000000}, + {0x9c40000000000000, 0x0000000000000000}, + {0xc350000000000000, 0x0000000000000000}, + {0xf424000000000000, 0x0000000000000000}, + {0x9896800000000000, 0x0000000000000000}, + {0xbebc200000000000, 0x0000000000000000}, + {0xee6b280000000000, 0x0000000000000000}, + {0x9502f90000000000, 0x0000000000000000}, + {0xba43b74000000000, 0x0000000000000000}, + {0xe8d4a51000000000, 0x0000000000000000}, + {0x9184e72a00000000, 0x0000000000000000}, + {0xb5e620f480000000, 0x0000000000000000}, + {0xe35fa931a0000000, 0x0000000000000000}, + {0x8e1bc9bf04000000, 0x0000000000000000}, + {0xb1a2bc2ec5000000, 0x0000000000000000}, + {0xde0b6b3a76400000, 0x0000000000000000}, + {0x8ac7230489e80000, 0x0000000000000000}, + {0xad78ebc5ac620000, 0x0000000000000000}, + {0xd8d726b7177a8000, 0x0000000000000000}, + {0x878678326eac9000, 0x0000000000000000}, + {0xa968163f0a57b400, 0x0000000000000000}, + {0xd3c21bcecceda100, 0x0000000000000000}, + {0x84595161401484a0, 0x0000000000000000}, + {0xa56fa5b99019a5c8, 0x0000000000000000}, + {0xcecb8f27f4200f3a, 0x0000000000000000}, + {0x813f3978f8940984, 0x4000000000000000}, + {0xa18f07d736b90be5, 0x5000000000000000}, + {0xc9f2c9cd04674ede, 0xa400000000000000}, + {0xfc6f7c4045812296, 0x4d00000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xc5371912364ce305, 0x6c28000000000000}, + {0xf684df56c3e01bc6, 0xc732000000000000}, + {0x9a130b963a6c115c, 0x3c7f400000000000}, + {0xc097ce7bc90715b3, 0x4b9f100000000000}, + {0xf0bdc21abb48db20, 0x1e86d40000000000}, + {0x96769950b50d88f4, 0x1314448000000000}, + {0xbc143fa4e250eb31, 0x17d955a000000000}, + {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, + {0x92efd1b8d0cf37be, 0x5aa1cae500000000}, + {0xb7abc627050305ad, 0xf14a3d9e40000000}, + {0xe596b7b0c643c719, 0x6d9ccd05d0000000}, + {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, + {0xb35dbf821ae4f38b, 0xdda2802c8a800000}, + {0xe0352f62a19e306e, 0xd50b2037ad200000}, + {0x8c213d9da502de45, 0x4526f422cc340000}, + {0xaf298d050e4395d6, 0x9670b12b7f410000}, + {0xdaf3f04651d47b4c, 0x3c0cdd765f114000}, + {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, + {0xab0e93b6efee0053, 0x8eea0d047a457a00}, + {0xd5d238a4abe98068, 0x72a4904598d6d880}, + {0x85a36366eb71f041, 0x47a6da2b7f864750}, + {0xa70c3c40a64e6c51, 0x999090b65f67d924}, + {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d}, + {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0e}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0x9f4f2726179a2245, 0x01d762422c946591}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb30}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7b}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b617}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe42}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebf}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, + {0xacb92ed9397bf996, 0x49c2c37f07965405}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30191}, + {0x83c7088e1aab65db, 0x792667c6da79e0fb}, + {0xa4b8cab1a1563f52, 0x577001b891185939}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0x80b05e5ac60b6178, 0x544f8158315b05b5}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38ea}, + {0xfb5878494ace3a5f, 0x04ab48a04065c724}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, + {0xf5746577930d6500, 0xca8f44ec7ee3647a}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a13}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, + {0xea1575143cf97226, 0xf52d09d71a3293be}, + {0x924d692ca61be758, 0x593c2626705f9c57}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, + {0x8edf98b59a373fec, 0x4724bd4189bd5ead}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee}, + {0x8b865b215899f46c, 0xbd79e0d20082ee75}, + {0xae67f1e9aec07187, 0xecd8590680a3aa12}, + {0xda01ee641a708de9, 0xe80e6f4820cc9496}, + {0x884134fe908658b2, 0x3109058d147fdcde}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0xcfe87f7cef46ff16, 0xe612641865679a64}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f}, + {0xa26da3999aef7749, 0xe3be5e330f38f09e}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb}, + {0xc646d63501a1511d, 0xb281e1fd541501b9}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4227}, + {0x9ae757596946075f, 0x3375788de9b06959}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83af}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e1}, + {0xbd176620a501fbff, 0xb650e5a93bc3d899}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf}, + {0x93ba47c980e98cdf, 0xc66f336c36b10138}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4185}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, + {0x9043ea1ac7e41392, 0x87c89837ad68db30}, + {0xb454e4a179dd1877, 0x29babe4598c311fc}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90}, + {0xdc21a1171d42645d, 0x76707543f4fa1f74}, + {0x899504ae72497eba, 0x6a06494a791c53a9}, + {0xabfa45da0edbde69, 0x0487db9d17636893}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b7}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xa7f26836f282b732, 0x8e6cac7768d7141f}, + {0xd1ef0244af2364ff, 0x3207d795430cd927}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b9}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, + {0xcd036837130890a1, 0x36dba887c37a8c10}, + {0x802221226be55a64, 0xc2494954da2c978a}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa}, + {0x9c69a97284b578d7, 0xff2a760414536efc}, + {0xc38413cf25e2d70d, 0xfef5138519684abb}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a62}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, + {0xba756174393d88df, 0x94f971119aeef9e5}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, + {0x91abb422ccb812ee, 0xac62e055c10ab33b}, + {0xb616a12b7fe617aa, 0x577b986b314d600a}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c}, + {0x8e41ade9fbebc27d, 0x14588f13be847308}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, + {0x8aec23d680043bee, 0x25de7bb9480d5855}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0x87aa9aff79042286, 0x90fb44d2f05d0843}, + {0xa99541bf57452b28, 0x353a1607ac744a54}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, + {0x847c9b5d7c2e09b7, 0x69956135febada12}, + {0xa59bc234db398c25, 0x43fab9837e699096}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731733}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43f}, + {0x9defbf01b061adab, 0x3a0888136afa64a8}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd1}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864c}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, + {0xbc4665b596706114, 0x873d5d9f0dde1fef}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f3}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb}, + {0x8fa475791a569d10, 0xf96e017d694487bd}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ad}, + {0xe070f78d3927556a, 0x85bbe253f47b1418}, + {0x8c469ab843b89562, 0x93956d7478ccec8f}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f}, + {0x88fcf317f22241e2, 0x441fece3bdf81f04}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c4}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, + {0x85c7056562757456, 0xf6872d5667844e4a}, + {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, + {0xd106f86e69d785c7, 0xe13336d701beba53}, + {0x82a45b450226b39c, 0xecc0024661173474}, + {0xa34d721642b06084, 0x27f002d7f95d0191}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, + {0xff290242c83396ce, 0x7e67047175a15272}, + {0x9f79a169bd203e41, 0x0f0062c6e984d387}, + {0xc75809c42c684dd1, 0x52c07b78a3e60869}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb692}, + {0xc2abf989935ddbfe, 0x6acff893d00ea436}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d44}, + {0x98165af37b2153de, 0xc3727a337a8b704b}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d}, + {0xeda2ee1c7064130c, 0x1162def06f79df74}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xb10d8e1456105dad, 0x7425a83e872c5f48}, + {0xdd50f1996b947518, 0xd12f124e28f7771a}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550c}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, + {0x8714a775e3e95c78, 0x65acfaec34810a72}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, + {0xd31045a8341ca07c, 0x1ede48111209a051}, + {0x83ea2b892091e44d, 0x934aed0aab460433}, + {0xa4e4b66b68b65d60, 0xf81da84d56178540}, + {0xce1de40642e3f4b9, 0x36251260ab9d668f}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a}, + {0xa1075a24e4421730, 0xb24cf65b8612f820}, + {0xc94930ae1d529cfc, 0xdee033f26797b628}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864f}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af4}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, + {0xea53df5fd18d5513, 0x84c86189216dc5ee}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, + {0xdf78e4b2bd342cf6, 0x914da9246b255417}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, + {0xae9672aba3d0c320, 0xa184ac2473b529b2}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, + {0x8865899617fb1871, 0x7e2fa67c7a658893}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, + {0xd51ea6fa85785631, 0x552a74227f3ea566}, + {0x8533285c936b35de, 0xd53a88958f872760}, + {0xa67ff273b8460356, 0x8a892abaf368f138}, + {0xd01fef10a657842c, 0x2d2b7569b0432d86}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc74}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, + {0xcb3f2f7642717713, 0x241c70a936219a74}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, + {0x9ec95d1463e8a506, 0xf4363804324a40ab}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050b}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, + {0x976e41088617ca01, 0xd5be0503e085d814}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219f}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, + {0x906a617d450187e2, 0x27fb2b80668b24c6}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, + {0xe1a63853bbd26451, 0x5e7873f8a0396974}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e}, + {0xac2820d9623bf429, 0x546345fa9fbdcd45}, + {0xd732290fbacaf133, 0xa97c177947ad4096}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a75}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, + {0xa0555e361951c366, 0xd7e105bcc3326220}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, + {0xfa856334878fc150, 0xb14f98f6f0feb952}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c9}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, + {0xeeea5d5004981478, 0x1858ccfce06cac75}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, + {0xbaa718e68396cffd, 0xd30560258f54e6bb}, + {0xe950df20247c83fd, 0x47c6b82ef32a206a}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5442}, + {0xb6472e511c81471d, 0xe0133fe4adf8e953}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a7}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, + {0xb201833b35d63f73, 0x2cd2cc6551e513db}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, + {0x8b112e86420f6191, 0xfb04afaf27faf783}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, + {0xd94ad8b1c7380874, 0x18375281ae7822bd}, + {0x87cec76f1c830548, 0x8f2293910d0b15b6}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23}, + {0xd433179d9c8cb841, 0x5fa60692a46151ec}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd334}, + {0xa5c7ea73224deff3, 0x12b9b522906c0801}, + {0xcf39e50feae16bef, 0xd768226b34870a01}, + {0x81842f29f2cce375, 0xe6a1158300d46641}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd1}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, + {0xc5a05277621be293, 0xc7098b7305241886}, + {0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}, + {0x9a65406d44a5c903, 0x737f74f1dc043329}, + {0xc0fe908895cf3b44, 0x505f522e53053ff3}, + {0xf13e34aabb430a15, 0x647726b9e7c68ff0}, + {0x96c6e0eab509e64d, 0x5eca783430dc19f6}, + {0xbc789925624c5fe0, 0xb67d16413d132073}, + {0xeb96bf6ebadf77d8, 0xe41c5bd18c57e890}, + {0x933e37a534cbaae7, 0x8e91b962f7b6f15a}, + {0xb80dc58e81fe95a1, 0x723627bbb5a4adb1}, + {0xe61136f2227e3b09, 0xcec3b1aaa30dd91d}, + {0x8fcac257558ee4e6, 0x213a4f0aa5e8a7b2}, + {0xb3bd72ed2af29e1f, 0xa988e2cd4f62d19e}, + {0xe0accfa875af45a7, 0x93eb1b80a33b8606}, + {0x8c6c01c9498d8b88, 0xbc72f130660533c4}, + {0xaf87023b9bf0ee6a, 0xeb8fad7c7f8680b5}, + {0xdb68c2ca82ed2a05, 0xa67398db9f6820e2}, +#else + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0xc350000000000000, 0x0000000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, + {0xf13e34aabb430a15, 0x647726b9e7c68ff0} +#endif + }; + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return pow10_significands[k - float_info::min_k]; +#else + static constexpr const uint64_t powers_of_5_64[] = { + 0x0000000000000001, 0x0000000000000005, 0x0000000000000019, + 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35, + 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1, + 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd, + 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9, + 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5, + 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631, + 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed, + 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9}; + + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info::min_k; + int offset = k - kb; + + // Get base cache. + uint128_fallback base_cache = pow10_significands[cache_index]; + if (offset == 0) return base_cache; + + // Compute the required amount of bit-shift. + int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; + FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); + + // Try to recover the real cache. + uint64_t pow5 = powers_of_5_64[offset]; + uint128_fallback recovered_cache = umul128(base_cache.high(), pow5); + uint128_fallback middle_low = umul128(base_cache.low(), pow5); + + recovered_cache += middle_low.high(); + + uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); + uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); + + recovered_cache = + uint128_fallback{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + FMT_ASSERT(recovered_cache.low() + 1 != 0, ""); + return {recovered_cache.high(), recovered_cache.low() + 1}; +#endif + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static auto compute_mul(carrier_uint u, + const cache_entry_type& cache) noexcept + -> compute_mul_result { + auto r = umul192_upper128(u, cache); + return {r.high(), r.low() == 0}; + } + + static auto compute_delta(const cache_entry_type& cache, int beta) noexcept + -> uint32_t { + return static_cast(cache.high() >> (64 - 1 - beta)); + } + + static auto compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta) noexcept + -> compute_mul_parity_result { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul192_lower128(two_f, cache); + return {((r.high() >> (64 - beta)) & 1) != 0, + ((r.high() << beta) | (r.low() >> (64 - beta))) == 0}; + } + + static auto compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (cache.high() - + (cache.high() >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static auto compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (cache.high() + + (cache.high() >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static auto compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return ((cache.high() >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +FMT_FUNC auto get_cached_power(int k) noexcept -> uint128_fallback { + return cache_accessor::get_cached_power(k); +} + +// Various integer checks +template +auto is_left_endpoint_integer_shorter_interval(int exponent) noexcept -> bool { + const int case_shorter_interval_left_endpoint_lower_threshold = 2; + const int case_shorter_interval_left_endpoint_upper_threshold = 3; + return exponent >= case_shorter_interval_left_endpoint_lower_threshold && + exponent <= case_shorter_interval_left_endpoint_upper_threshold; +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_INLINE int remove_trailing_zeros(uint32_t& n, int s = 0) noexcept { + FMT_ASSERT(n != 0, ""); + // Modular inverse of 5 (mod 2^32): (mod_inv_5 * 5) mod 2^32 = 1. + constexpr uint32_t mod_inv_5 = 0xcccccccd; + constexpr uint32_t mod_inv_25 = 0xc28f5c29; // = mod_inv_5 * mod_inv_5 + + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept { + FMT_ASSERT(n != 0, ""); + + // This magic number is ceil(2^90 / 10^8). + constexpr uint64_t magic_number = 12379400392853802749ull; + auto nm = umul128(n, magic_number); + + // Is n is divisible by 10^8? + if ((nm.high() & ((1ull << (90 - 64)) - 1)) == 0 && nm.low() < magic_number) { + // If yes, work with the quotient... + auto n32 = static_cast(nm.high() >> (90 - 64)); + // ... and use the 32 bit variant of the function + int s = remove_trailing_zeros(n32, 8); + n = n32; + return s; + } + + // If n is not divisible by 10^8, work with n itself. + constexpr uint64_t mod_inv_5 = 0xcccccccccccccccd; + constexpr uint64_t mod_inv_25 = 0x8f5c28f5c28f5c29; // mod_inv_5 * mod_inv_5 + + int s = 0; + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + + return s; +} + +// The main algorithm for shorter interval case +template +FMT_INLINE decimal_fp shorter_interval_case(int exponent) noexcept { + decimal_fp ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor::cache_entry_type; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + + auto xi = cache_accessor::compute_left_endpoint_for_shorter_interval_case( + cache, beta); + auto zi = cache_accessor::compute_right_endpoint_for_shorter_interval_case( + cache, beta); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval(exponent)) ++xi; + + // Try bigger divisor + ret_value.significand = zi / 10; + + // If succeed, remove trailing zeros if necessary and return + if (ret_value.significand * 10 >= xi) { + ret_value.exponent = minus_k + 1; + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + } + + // Otherwise, compute the round-up of y + ret_value.significand = + cache_accessor::compute_round_up_for_shorter_interval_case(cache, + beta); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info::shorter_interval_tie_lower_threshold && + exponent <= float_info::shorter_interval_tie_upper_threshold) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } else if (ret_value.significand < xi) { + ++ret_value.significand; + } + return ret_value; +} + +template auto to_decimal(T x) noexcept -> decimal_fp { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info::carrier_uint; + using cache_entry_type = typename cache_accessor::cache_entry_type; + auto br = bit_cast(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast(1) << num_significand_bits()) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = + static_cast((br & exponent_mask()) >> num_significand_bits()); + + if (exponent != 0) { // Check if normal. + exponent -= exponent_bias() + num_significand_bits(); + + // Shorter interval case; proceed like Schubfach. + // In fact, when exponent == 1 and significand == 0, the interval is + // regular. However, it can be shown that the end-results are anyway same. + if (significand == 0) return shorter_interval_case(exponent); + + significand |= (static_cast(1) << num_significand_bits()); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = + std::numeric_limits::min_exponent - num_significand_bits() - 1; + } + + const bool include_left_endpoint = (significand % 2 == 0); + const bool include_right_endpoint = include_left_endpoint; + + // Compute k and beta. + const int minus_k = floor_log10_pow2(exponent) - float_info::kappa; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai. + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor::compute_delta(cache, beta); + const carrier_uint two_fc = significand << 1; + + // For the case of binary32, the result of integer check is not correct for + // 29711844 * 2^-82 + // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18 + // and 29711844 * 2^-81 + // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17, + // and they are the unique counterexamples. However, since 29711844 is even, + // this does not cause any problem for the endpoints calculations; it can only + // cause a problem when we need to perform integer check for the center. + // Fortunately, with these inputs, that branch is never executed, so we are + // fine. + const typename cache_accessor::compute_mul_result z_mul = + cache_accessor::compute_mul((two_fc | 1) << beta, cache); + + // Step 2: Try larger divisor; remove trailing zeros if necessary. + + // Using an upper bound on zi, we might be able to optimize the division + // better than the compiler; we are computing zi / big_divisor here. + decimal_fp ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(z_mul.result); + uint32_t r = static_cast(z_mul.result - float_info::big_divisor * + ret_value.significand); + + if (r < deltai) { + // Exclude the right endpoint if necessary. + if (r == 0 && (z_mul.is_integer & !include_right_endpoint)) { + --ret_value.significand; + r = float_info::big_divisor; + goto small_divisor_case_label; + } + } else if (r > deltai) { + goto small_divisor_case_label; + } else { + // r == deltai; compare fractional parts. + const typename cache_accessor::compute_mul_parity_result x_mul = + cache_accessor::compute_mul_parity(two_fc - 1, cache, beta); + + if (!(x_mul.parity | (x_mul.is_integer & include_left_endpoint))) + goto small_divisor_case_label; + } + ret_value.exponent = minus_k + float_info::kappa + 1; + + // We may need to remove trailing zeros. + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + + // Step 3: Find the significand with the smaller divisor. + +small_divisor_case_label: + ret_value.significand *= 10; + ret_value.exponent = minus_k + float_info::kappa; + + uint32_t dist = r - (deltai / 2) + (float_info::small_divisor / 2); + const bool approx_y_parity = + ((dist ^ (float_info::small_divisor / 2)) & 1) != 0; + + // Is dist divisible by 10^kappa? + const bool divisible_by_small_divisor = + check_divisibility_and_divide_by_pow10::kappa>(dist); + + // Add dist / 10^kappa to the significand. + ret_value.significand += dist; + + if (!divisible_by_small_divisor) return ret_value; + + // Check z^(f) >= epsilon^(f). + // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, + // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f). + // Since there are only 2 possibilities, we only need to care about the + // parity. Also, zi and r should have the same parity since the divisor + // is an even number. + const auto y_mul = cache_accessor::compute_mul_parity(two_fc, cache, beta); + + // If z^(f) >= epsilon^(f), we might have a tie when z^(f) == epsilon^(f), + // or equivalently, when y is an integer. + if (y_mul.parity != approx_y_parity) + --ret_value.significand; + else if (y_mul.is_integer & (ret_value.significand % 2 != 0)) + --ret_value.significand; + return ret_value; +} +} // namespace dragonbox +} // namespace detail + +template <> struct formatter { + FMT_CONSTEXPR auto parse(format_parse_context& ctx) + -> format_parse_context::iterator { + return ctx.begin(); + } + + auto format(const detail::bigint& n, format_context& ctx) const + -> format_context::iterator { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = fmt::format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = fmt::format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = fmt::format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; + +FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { + for_each_codepoint(s, [this](uint32_t cp, string_view) { + if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8")); + if (cp <= 0xFFFF) { + buffer_.push_back(static_cast(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast(0xDC00 + (cp & 0x3FF))); + } + return true; + }); + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer& out, int error_code, + const char* message) noexcept { + FMT_TRY { + auto ec = std::error_code(error_code, std::generic_category()); + detail::write(appender(out), std::system_error(ec, message).what()); + return; + } + FMT_CATCH(...) {} + format_error_code(out, error_code, message); +} + +FMT_FUNC void report_system_error(int error_code, + const char* message) noexcept { + do_report_error(format_system_error, error_code, message); +} + +FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string { + // Don't optimize the "{}" case to keep the binary size small and because it + // can be better optimized in fmt::format anyway. + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + return to_string(buffer); +} + +namespace detail { + +FMT_FUNC void vformat_to(buffer& buf, string_view fmt, format_args args, + locale_ref loc) { + auto out = appender(buf); + if (fmt.size() == 2 && equal2(fmt.data(), "{}")) + return args.get(0).visit(default_arg_formatter{out}); + parse_format_string( + fmt, format_handler{parse_context(fmt), {out, args, loc}}); +} + +template struct span { + T* data; + size_t size; +}; + +template auto flockfile(F* f) -> decltype(_lock_file(f)) { + _lock_file(f); +} +template auto funlockfile(F* f) -> decltype(_unlock_file(f)) { + _unlock_file(f); +} + +#ifndef getc_unlocked +template auto getc_unlocked(F* f) -> decltype(_fgetc_nolock(f)) { + return _fgetc_nolock(f); +} +#endif + +template +struct has_flockfile : std::false_type {}; + +template +struct has_flockfile()))>> + : std::true_type {}; + +// A FILE wrapper. F is FILE defined as a template parameter to make system API +// detection work. +template class file_base { + public: + F* file_; + + public: + file_base(F* file) : file_(file) {} + operator F*() const { return file_; } + + // Reads a code unit from the stream. + auto get() -> int { + int result = getc_unlocked(file_); + if (result == EOF && ferror(file_) != 0) + FMT_THROW(system_error(errno, FMT_STRING("getc failed"))); + return result; + } + + // Puts the code unit back into the stream buffer. + void unget(char c) { + if (ungetc(c, file_) == EOF) + FMT_THROW(system_error(errno, FMT_STRING("ungetc failed"))); + } + + void flush() { fflush(this->file_); } +}; + +// A FILE wrapper for glibc. +template class glibc_file : public file_base { + private: + enum { + line_buffered = 0x200, // _IO_LINE_BUF + unbuffered = 2 // _IO_UNBUFFERED + }; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { + return (this->file_->_flags & unbuffered) == 0; + } + + void init_buffer() { + if (this->file_->_IO_write_ptr < this->file_->_IO_write_end) return; + // Force buffer initialization by placing and removing a char in a buffer. + putc_unlocked(0, this->file_); + --this->file_->_IO_write_ptr; + } + + // Returns the file's read buffer. + auto get_read_buffer() const -> span { + auto ptr = this->file_->_IO_read_ptr; + return {ptr, to_unsigned(this->file_->_IO_read_end - ptr)}; + } + + // Returns the file's write buffer. + auto get_write_buffer() const -> span { + auto ptr = this->file_->_IO_write_ptr; + return {ptr, to_unsigned(this->file_->_IO_buf_end - ptr)}; + } + + void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; } + + bool needs_flush() const { + if ((this->file_->_flags & line_buffered) == 0) return false; + char* end = this->file_->_IO_write_end; + return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end)); + } + + void flush() { fflush_unlocked(this->file_); } +}; + +// A FILE wrapper for Apple's libc. +template class apple_file : public file_base { + private: + enum { + line_buffered = 1, // __SNBF + unbuffered = 2 // __SLBF + }; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { + return (this->file_->_flags & unbuffered) == 0; + } + + void init_buffer() { + if (this->file_->_p) return; + // Force buffer initialization by placing and removing a char in a buffer. + putc_unlocked(0, this->file_); + --this->file_->_p; + ++this->file_->_w; + } + + auto get_read_buffer() const -> span { + return {reinterpret_cast(this->file_->_p), + to_unsigned(this->file_->_r)}; + } + + auto get_write_buffer() const -> span { + return {reinterpret_cast(this->file_->_p), + to_unsigned(this->file_->_bf._base + this->file_->_bf._size - + this->file_->_p)}; + } + + void advance_write_buffer(size_t size) { + this->file_->_p += size; + this->file_->_w -= size; + } + + bool needs_flush() const { + if ((this->file_->_flags & line_buffered) == 0) return false; + return memchr(this->file_->_p + this->file_->_w, '\n', + to_unsigned(-this->file_->_w)); + } +}; + +// A fallback FILE wrapper. +template class fallback_file : public file_base { + private: + char next_; // The next unconsumed character in the buffer. + bool has_next_ = false; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { return false; } + auto needs_flush() const -> bool { return false; } + void init_buffer() {} + + auto get_read_buffer() const -> span { + return {&next_, has_next_ ? 1u : 0u}; + } + + auto get_write_buffer() const -> span { return {nullptr, 0}; } + + void advance_write_buffer(size_t) {} + + auto get() -> int { + has_next_ = false; + return file_base::get(); + } + + void unget(char c) { + file_base::unget(c); + next_ = c; + has_next_ = true; + } +}; + +#ifndef FMT_USE_FALLBACK_FILE +# define FMT_USE_FALLBACK_FILE 0 +#endif + +template +auto get_file(F* f, int) -> apple_file { + return f; +} +template +inline auto get_file(F* f, int) -> glibc_file { + return f; +} + +inline auto get_file(FILE* f, ...) -> fallback_file { return f; } + +using file_ref = decltype(get_file(static_cast(nullptr), 0)); + +template +class file_print_buffer : public buffer { + public: + explicit file_print_buffer(F*) : buffer(nullptr, size_t()) {} +}; + +template +class file_print_buffer::value>> + : public buffer { + private: + file_ref file_; + + static void grow(buffer& base, size_t) { + auto& self = static_cast(base); + self.file_.advance_write_buffer(self.size()); + if (self.file_.get_write_buffer().size == 0) self.file_.flush(); + auto buf = self.file_.get_write_buffer(); + FMT_ASSERT(buf.size > 0, ""); + self.set(buf.data, buf.size); + self.clear(); + } + + public: + explicit file_print_buffer(F* f) : buffer(grow, size_t()), file_(f) { + flockfile(f); + file_.init_buffer(); + auto buf = file_.get_write_buffer(); + set(buf.data, buf.size); + } + ~file_print_buffer() { + file_.advance_write_buffer(size()); + bool flush = file_.needs_flush(); + F* f = file_; // Make funlockfile depend on the template parameter F + funlockfile(f); // for the system API detection to work. + if (flush) fflush(file_); + } +}; + +#if !defined(_WIN32) || defined(FMT_USE_WRITE_CONSOLE) +FMT_FUNC auto write_console(int, string_view) -> bool { return false; } +#else +using dword = conditional_t; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); + +FMT_FUNC bool write_console(int fd, string_view text) { + auto u16 = utf8_to_utf16(text); + return WriteConsoleW(reinterpret_cast(_get_osfhandle(fd)), u16.c_str(), + static_cast(u16.size()), nullptr, nullptr) != 0; +} +#endif + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void vprint_mojibake(std::FILE* f, string_view fmt, format_args args, + bool newline) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + if (newline) buffer.push_back('\n'); + fwrite_all(buffer.data(), buffer.size(), f); +} +#endif + +FMT_FUNC void print(std::FILE* f, string_view text) { +#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE) + int fd = _fileno(f); + if (_isatty(fd)) { + std::fflush(f); + if (write_console(fd, text)) return; + } +#endif + fwrite_all(text.data(), text.size(), f); +} +} // namespace detail + +FMT_FUNC void vprint_buffered(std::FILE* f, string_view fmt, format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + detail::print(f, {buffer.data(), buffer.size()}); +} + +FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { + if (!detail::file_ref(f).is_buffered() || !detail::has_flockfile<>()) + return vprint_buffered(f, fmt, args); + auto&& buffer = detail::file_print_buffer<>(f); + return detail::vformat_to(buffer, fmt, args); +} + +FMT_FUNC void vprintln(std::FILE* f, string_view fmt, format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + buffer.push_back('\n'); + detail::print(f, {buffer.data(), buffer.size()}); +} + +FMT_FUNC void vprint(string_view fmt, format_args args) { + vprint(stdout, fmt, args); +} + +namespace detail { + +struct singleton { + unsigned char upper; + unsigned char lower_count; +}; + +inline auto is_printable(uint16_t x, const singleton* singletons, + size_t singletons_size, + const unsigned char* singleton_lowers, + const unsigned char* normal, size_t normal_size) + -> bool { + auto upper = x >> 8; + auto lower_start = 0; + for (size_t i = 0; i < singletons_size; ++i) { + auto s = singletons[i]; + auto lower_end = lower_start + s.lower_count; + if (upper < s.upper) break; + if (upper == s.upper) { + for (auto j = lower_start; j < lower_end; ++j) { + if (singleton_lowers[j] == (x & 0xff)) return false; + } + } + lower_start = lower_end; + } + + auto xsigned = static_cast(x); + auto current = true; + for (size_t i = 0; i < normal_size; ++i) { + auto v = static_cast(normal[i]); + auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v; + xsigned -= len; + if (xsigned < 0) break; + current = !current; + } + return current; +} + +// This code is generated by support/printable.py. +FMT_FUNC auto is_printable(uint32_t cp) -> bool { + static constexpr singleton singletons0[] = { + {0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8}, + {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13}, + {0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5}, + {0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22}, + {0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3}, + {0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8}, + {0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9}, + }; + static constexpr unsigned char singletons0_lower[] = { + 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90, + 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, + 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1, + 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, + 0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d, + 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, + 0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, + 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d, + 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d, + 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, + 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7, + 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, + 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7, + 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, + 0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, + 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, + 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, + 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, + 0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, + 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, + 0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, + 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, + 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, + }; + static constexpr singleton singletons1[] = { + {0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2}, + {0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5}, + {0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5}, + {0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2}, + {0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5}, + {0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2}, + {0xfa, 2}, {0xfb, 1}, + }; + static constexpr unsigned char singletons1_lower[] = { + 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, + 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, + 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87, + 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9, + 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, + 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, + 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, + 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6, + 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, + 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, + 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, + 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93, + }; + static constexpr unsigned char normal0[] = { + 0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04, + 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0, + 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01, + 0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03, + 0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03, + 0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a, + 0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15, + 0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f, + 0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80, + 0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07, + 0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06, + 0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04, + 0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac, + 0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c, + 0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11, + 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c, + 0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b, + 0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6, + 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03, + 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80, + 0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06, + 0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c, + 0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17, + 0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80, + 0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80, + 0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d, + }; + static constexpr unsigned char normal1[] = { + 0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f, + 0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e, + 0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04, + 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09, + 0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16, + 0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f, + 0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36, + 0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33, + 0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08, + 0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e, + 0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41, + 0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03, + 0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22, + 0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04, + 0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45, + 0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03, + 0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81, + 0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75, + 0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1, + 0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a, + 0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11, + 0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09, + 0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89, + 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6, + 0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09, + 0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50, + 0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05, + 0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83, + 0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05, + 0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80, + 0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80, + 0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07, + 0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e, + 0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07, + 0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06, + }; + auto lower = static_cast(cp); + if (cp < 0x10000) { + return is_printable(lower, singletons0, + sizeof(singletons0) / sizeof(*singletons0), + singletons0_lower, normal0, sizeof(normal0)); + } + if (cp < 0x20000) { + return is_printable(lower, singletons1, + sizeof(singletons1) / sizeof(*singletons1), + singletons1_lower, normal1, sizeof(normal1)); + } + if (0x2a6de <= cp && cp < 0x2a700) return false; + if (0x2b735 <= cp && cp < 0x2b740) return false; + if (0x2b81e <= cp && cp < 0x2b820) return false; + if (0x2cea2 <= cp && cp < 0x2ceb0) return false; + if (0x2ebe1 <= cp && cp < 0x2f800) return false; + if (0x2fa1e <= cp && cp < 0x30000) return false; + if (0x3134b <= cp && cp < 0xe0100) return false; + if (0xe01f0 <= cp && cp < 0x110000) return false; + return cp < 0x110000; +} + +} // namespace detail + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/format.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/format.h new file mode 100755 index 0000000000000000000000000000000000000000..5efb8e6175cc7cb68d4a8926c5706f9832a477dd --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/format.h @@ -0,0 +1,4244 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - present, Victor Zverovich + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --- Optional exception to the license --- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into a machine-executable object form of such + source code, you may redistribute such embedded portions in such object form + without including the above copyright and permission notices. + */ + +#ifndef FMT_FORMAT_H_ +#define FMT_FORMAT_H_ + +#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +# define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +# define FMT_REMOVE_TRANSITIVE_INCLUDES +#endif + +#include "base.h" + +#ifndef FMT_MODULE +# include // std::signbit +# include // std::byte +# include // uint32_t +# include // std::memcpy +# include // std::numeric_limits +# include // std::bad_alloc +# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) +// Workaround for pre gcc 5 libstdc++. +# include // std::allocator_traits +# endif +# include // std::runtime_error +# include // std::string +# include // std::system_error + +// Check FMT_CPLUSPLUS to avoid a warning in MSVC. +# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L +# include // std::bit_cast +# endif + +// libc++ supports string_view in pre-c++17. +# if FMT_HAS_INCLUDE() && \ + (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) +# include +# define FMT_USE_STRING_VIEW +# endif + +# if FMT_MSC_VERSION +# include // _BitScanReverse[64], _umul128 +# endif +#endif // FMT_MODULE + +#if defined(FMT_USE_NONTYPE_TEMPLATE_ARGS) +// Use the provided definition. +#elif defined(__NVCOMPILER) +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 +#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#elif defined(__cpp_nontype_template_args) && \ + __cpp_nontype_template_args >= 201911L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#else +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 +#endif + +#if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L +# define FMT_INLINE_VARIABLE inline +#else +# define FMT_INLINE_VARIABLE +#endif + +// Check if RTTI is disabled. +#ifdef FMT_USE_RTTI +// Use the provided definition. +#elif defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \ + defined(__INTEL_RTTI__) || defined(__RTTI) +// __RTTI is for EDG compilers. _CPPRTTI is for MSVC. +# define FMT_USE_RTTI 1 +#else +# define FMT_USE_RTTI 0 +#endif + +// Visibility when compiled as a shared library/object. +#if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) +# define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value) +#else +# define FMT_SO_VISIBILITY(value) +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_NOINLINE __attribute__((noinline)) +#else +# define FMT_NOINLINE +#endif + +// GCC 4.9 doesn't support qualified names in specializations. +namespace std { +template struct iterator_traits> { + using iterator_category = output_iterator_tag; + using value_type = T; + using difference_type = + decltype(static_cast(nullptr) - static_cast(nullptr)); + using pointer = void; + using reference = void; +}; +} // namespace std + +#ifndef FMT_THROW +# if FMT_USE_EXCEPTIONS +# if FMT_MSC_VERSION || defined(__NVCC__) +FMT_BEGIN_NAMESPACE +namespace detail { +template inline void do_throw(const Exception& x) { + // Silence unreachable code warnings in MSVC and NVCC because these + // are nearly impossible to fix in a generic code. + volatile bool b = true; + if (b) throw x; +} +} // namespace detail +FMT_END_NAMESPACE +# define FMT_THROW(x) detail::do_throw(x) +# else +# define FMT_THROW(x) throw x +# endif +# else +# define FMT_THROW(x) \ + ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what()) +# endif // FMT_USE_EXCEPTIONS +#endif // FMT_THROW + +// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of +// integer formatter template instantiations to just one by only using the +// largest integer type. This results in a reduction in binary size but will +// cause a decrease in integer formatting performance. +#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) +# define FMT_REDUCE_INT_INSTANTIATIONS 0 +#endif + +FMT_BEGIN_NAMESPACE + +template +struct is_contiguous> + : std::true_type {}; + +namespace detail { + +// __builtin_clz is broken in clang with Microsoft codegen: +// https://github.com/fmtlib/fmt/issues/519. +#if !FMT_MSC_VERSION +# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# endif +#endif + +// Some compilers masquerade as both MSVC and GCC but otherwise support +// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the +// MSVC intrinsics if the clz and clzll builtins are not available. +#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) +// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. +# ifndef __clang__ +# pragma intrinsic(_BitScanReverse) +# ifdef _WIN64 +# pragma intrinsic(_BitScanReverse64) +# endif +# endif + +inline auto clz(uint32_t x) -> int { + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + unsigned long r = 0; + _BitScanReverse(&r, x); + return 31 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZ(n) detail::clz(n) + +inline auto clzll(uint64_t x) -> int { + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) + return 63 ^ static_cast(r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x)); +# endif + return 63 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) +#endif // FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) + +FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) { + ignore_unused(condition); +#ifdef FMT_FUZZ + if (condition) throw std::runtime_error("fuzzing limit reached"); +#endif +} + +#if defined(FMT_USE_STRING_VIEW) +template using std_string_view = std::basic_string_view; +#else +template struct std_string_view { + operator basic_string_view() const; +}; +#endif + +template struct string_literal { + static constexpr Char value[sizeof...(C)] = {C...}; + constexpr operator basic_string_view() const { + return {value, sizeof...(C)}; + } +}; +#if FMT_CPLUSPLUS < 201703L +template +constexpr Char string_literal::value[sizeof...(C)]; +#endif + +// Implementation of std::bit_cast for pre-C++20. +template +FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) return std::bit_cast(from); +#endif + auto to = To(); + // The cast suppresses a bogus -Wclass-memaccess on GCC. + std::memcpy(static_cast(&to), &from, sizeof(to)); + return to; +} + +inline auto is_big_endian() -> bool { +#ifdef _WIN32 + return false; +#elif defined(__BIG_ENDIAN__) + return true; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) + return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; +#else + struct bytes { + char data[sizeof(int)]; + }; + return bit_cast(1).data[0] == 0; +#endif +} + +class uint128_fallback { + private: + uint64_t lo_, hi_; + + public: + constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} + constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} + + constexpr auto high() const noexcept -> uint64_t { return hi_; } + constexpr auto low() const noexcept -> uint64_t { return lo_; } + + template ::value)> + constexpr explicit operator T() const { + return static_cast(lo_); + } + + friend constexpr auto operator==(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; + } + friend constexpr auto operator!=(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return !(lhs == rhs); + } + friend constexpr auto operator>(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_; + } + friend constexpr auto operator|(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_}; + } + friend constexpr auto operator&(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; + } + friend constexpr auto operator~(const uint128_fallback& n) + -> uint128_fallback { + return {~n.hi_, ~n.lo_}; + } + friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + auto result = uint128_fallback(lhs); + result += rhs; + return result; + } + friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs) + -> uint128_fallback { + FMT_ASSERT(lhs.hi_ == 0, ""); + uint64_t hi = (lhs.lo_ >> 32) * rhs; + uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs; + uint64_t new_lo = (hi << 32) + lo; + return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo}; + } + friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs) + -> uint128_fallback { + return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs}; + } + FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { + if (shift == 64) return {0, hi_}; + if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64); + return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; + } + FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { + if (shift == 64) return {lo_, 0}; + if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64); + return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; + } + FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { + return *this = *this >> shift; + } + FMT_CONSTEXPR void operator+=(uint128_fallback n) { + uint64_t new_lo = lo_ + n.lo_; + uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0); + FMT_ASSERT(new_hi >= hi_, ""); + lo_ = new_lo; + hi_ = new_hi; + } + FMT_CONSTEXPR void operator&=(uint128_fallback n) { + lo_ &= n.lo_; + hi_ &= n.hi_; + } + + FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& { + if (is_constant_evaluated()) { + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); + return *this; + } +#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__) + unsigned long long carry; + lo_ = __builtin_addcll(lo_, n, 0, &carry); + hi_ += carry; +#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__) + unsigned long long result; + auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result); + lo_ = result; + hi_ += carry; +#elif defined(_MSC_VER) && defined(_M_X64) + auto carry = _addcarry_u64(0, lo_, n, &lo_); + _addcarry_u64(carry, hi_, 0, &hi_); +#else + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); +#endif + return *this; + } +}; + +using uint128_t = conditional_t; + +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +#else +using uintptr_t = uint128_t; +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits::max() but shorter and not affected by the max macro. +template constexpr auto max_value() -> T { + return (std::numeric_limits::max)(); +} +template constexpr auto num_bits() -> int { + return std::numeric_limits::digits; +} +// std::numeric_limits::digits may return 0 for 128-bit ints. +template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } + +// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t +// and 128-bit pointers to uint128_fallback. +template sizeof(From))> +inline auto bit_cast(const From& from) -> To { + constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned short)); + struct data_t { + unsigned short value[static_cast(size)]; + } data = bit_cast(from); + auto result = To(); + if (const_check(is_big_endian())) { + for (int i = 0; i < size; ++i) + result = (result << num_bits()) | data.value[i]; + } else { + for (int i = size - 1; i >= 0; --i) + result = (result << num_bits()) | data.value[i]; + } + return result; +} + +template +FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int { + int lz = 0; + constexpr UInt msb_mask = static_cast(1) << (num_bits() - 1); + for (; (n & msb_mask) == 0; n <<= 1) lz++; + return lz; +} + +FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n); +#endif + return countl_zero_fallback(n); +} + +FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n); +#endif + return countl_zero_fallback(n); +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION + __builtin_assume(condition); +#elif FMT_GCC_VERSION + if (!condition) __builtin_unreachable(); +#endif +} + +// Attempts to reserve space for n extra characters in the output range. +// Returns a pointer to the reserved range or a reference to it. +template ::value&& + is_contiguous::value)> +#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +FMT_CONSTEXPR20 inline auto +reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* { + auto& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return &c[size]; +} + +template +FMT_CONSTEXPR20 inline auto reserve(basic_appender it, size_t n) + -> basic_appender { + buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template +constexpr auto reserve(Iterator& it, size_t) -> Iterator& { + return it; +} + +template +using reserve_iterator = + remove_reference_t(), 0))>; + +template +constexpr auto to_pointer(OutputIt, size_t) -> T* { + return nullptr; +} +template +FMT_CONSTEXPR20 auto to_pointer(basic_appender it, size_t n) -> T* { + buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); + auto size = buf.size(); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template ::value&& + is_contiguous::value)> +inline auto base_iterator(OutputIt it, + typename OutputIt::container_type::value_type*) + -> OutputIt { + return it; +} + +template +constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { + return it; +} + +// is spectacularly slow to compile in C++20 so use a double_online fill_n +// instead (#1998). +template +FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value) + -> OutputIt { + for (Size i = 0; i < count; ++i) *out++ = value; + return out; +} +template +FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { + if (is_constant_evaluated()) return fill_n(out, count, value); + std::memset(out, value, to_unsigned(count)); + return out + count; +} + +template +FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy(begin, end, out); +} + +// A public domain branchless UTF-8 decoder by Christopher Wellons: +// https://github.com/skeeto/branchless-utf8 +/* Decode the next character, c, from s, reporting errors in e. + * + * Since this is a branchless decoder, four bytes will be read from the + * buffer regardless of the actual length of the next character. This + * means the buffer _must_ have at least three bytes of zero padding + * following the end of the data stream. + * + * Errors are reported in e, which will be non-zero if the parsed + * character was somehow invalid: invalid byte sequence, non-canonical + * encoding, or a surrogate half. + * + * The function returns a pointer to the next character. When an error + * occurs, this pointer will be a guess that depends on the particular + * error, but it will always advance at least one byte. + */ +FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) + -> const char* { + constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; + constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; + constexpr const int shiftc[] = {0, 18, 12, 6, 0}; + constexpr const int shifte[] = {0, 6, 4, 2, 0}; + + int len = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4" + [static_cast(*s) >> 3]; + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + const char* next = s + len + !len; + + using uchar = unsigned char; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + *c = uint32_t(uchar(s[0]) & masks[len]) << 18; + *c |= uint32_t(uchar(s[1]) & 0x3f) << 12; + *c |= uint32_t(uchar(s[2]) & 0x3f) << 6; + *c |= uint32_t(uchar(s[3]) & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + *e = (*c < mins[len]) << 6; // non-canonical encoding + *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? + *e |= (*c > 0x10FFFF) << 8; // out of range? + *e |= (uchar(s[1]) & 0xc0) >> 2; + *e |= (uchar(s[2]) & 0xc0) >> 4; + *e |= uchar(s[3]) >> 6; + *e ^= 0x2a; // top two bits of each tail byte correct? + *e >>= shifte[len]; + + return next; +} + +constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t(); + +// Invokes f(cp, sv) for every code point cp in s with sv being the string view +// corresponding to the code point. cp is invalid_code_point on error. +template +FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { + auto decode = [f](const char* buf_ptr, const char* ptr) { + auto cp = uint32_t(); + auto error = 0; + auto end = utf8_decode(buf_ptr, &cp, &error); + bool result = f(error ? invalid_code_point : cp, + string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr))); + return result ? (error ? buf_ptr + 1 : end) : nullptr; + }; + + auto p = s.data(); + const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. + if (s.size() >= block_size) { + for (auto end = p + s.size() - block_size + 1; p < end;) { + p = decode(p, p); + if (!p) return; + } + } + auto num_chars_left = to_unsigned(s.data() + s.size() - p); + if (num_chars_left == 0) return; + + // Suppress bogus -Wstringop-overflow. + if (FMT_GCC_VERSION) num_chars_left &= 3; + char buf[2 * block_size - 1] = {}; + copy(p, p + num_chars_left, buf); + const char* buf_ptr = buf; + do { + auto end = decode(buf_ptr, p); + if (!end) return; + p += end - buf_ptr; + buf_ptr = end; + } while (buf_ptr < buf + num_chars_left); +} + +template +inline auto compute_width(basic_string_view s) -> size_t { + return s.size(); +} + +// Computes approximate display width of a UTF-8 string. +FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t { + size_t num_code_points = 0; + // It is not a lambda for compatibility with C++14. + struct count_code_points { + size_t* count; + FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool { + *count += to_unsigned( + 1 + + (cp >= 0x1100 && + (cp <= 0x115f || // Hangul Jamo init. consonants + cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET + cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE: + (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) || + (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables + (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs + (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms + (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms + (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms + (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms + (cp >= 0x20000 && cp <= 0x2fffd) || // CJK + (cp >= 0x30000 && cp <= 0x3fffd) || + // Miscellaneous Symbols and Pictographs + Emoticons: + (cp >= 0x1f300 && cp <= 0x1f64f) || + // Supplemental Symbols and Pictographs: + (cp >= 0x1f900 && cp <= 0x1f9ff)))); + return true; + } + }; + // We could avoid branches by using utf8_decode directly. + for_each_codepoint(s, count_code_points{&num_code_points}); + return num_code_points; +} + +template +inline auto code_point_index(basic_string_view s, size_t n) -> size_t { + return min_of(n, s.size()); +} + +// Calculates the index of the nth code point in a UTF-8 string. +inline auto code_point_index(string_view s, size_t n) -> size_t { + size_t result = s.size(); + const char* begin = s.begin(); + for_each_codepoint(s, [begin, &n, &result](uint32_t, string_view sv) { + if (n != 0) { + --n; + return true; + } + result = to_unsigned(sv.begin() - begin); + return false; + }); + return result; +} + +template struct is_integral : std::is_integral {}; +template <> struct is_integral : std::true_type {}; +template <> struct is_integral : std::true_type {}; + +template +using is_signed = + std::integral_constant::is_signed || + std::is_same::value>; + +template +using is_integer = + bool_constant::value && !std::is_same::value && + !std::is_same::value && + !std::is_same::value>; + +#if defined(FMT_USE_FLOAT128) +// Use the provided definition. +#elif FMT_CLANG_VERSION >= 309 && FMT_HAS_INCLUDE() +# define FMT_USE_FLOAT128 1 +#elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \ + !defined(__STRICT_ANSI__) +# define FMT_USE_FLOAT128 1 +#else +# define FMT_USE_FLOAT128 0 +#endif +#if FMT_USE_FLOAT128 +using float128 = __float128; +#else +struct float128 {}; +#endif + +template using is_float128 = std::is_same; + +template struct is_floating_point : std::is_floating_point {}; +template <> struct is_floating_point : std::true_type {}; + +template ::value> +struct is_fast_float : bool_constant::is_iec559 && + sizeof(T) <= sizeof(double)> {}; +template struct is_fast_float : std::false_type {}; + +template +using is_double_double = bool_constant::digits == 106>; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +// An allocator that uses malloc/free to allow removing dependency on the C++ +// standard libary runtime. +template struct allocator { + using value_type = T; + + T* allocate(size_t n) { + FMT_ASSERT(n <= max_value() / sizeof(T), ""); + T* p = static_cast(malloc(n * sizeof(T))); + if (!p) FMT_THROW(std::bad_alloc()); + return p; + } + + void deallocate(T* p, size_t) { free(p); } +}; + +} // namespace detail + +FMT_BEGIN_EXPORT + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic f_memory allocation. +enum { inline_buffer_size = 500 }; + +/** + * A dynamically growing f_memory buffer for trivially copyable/constructible + * types with the first `SIZE` elements stored in the object itself. Most + * commonly used via the `memory_buffer` alias for `char`. + * + * **Example**: + * + * auto out = fmt::memory_buffer(); + * fmt::format_to(std::back_inserter(out), "The answer is {}.", 42); + * + * This will append "The answer is 42." to `out`. The buffer content can be + * converted to `std::string` with `to_string(out)`. + */ +template > +class basic_memory_buffer : public detail::buffer { + private: + T store_[SIZE]; + + // Don't inherit from Allocator to avoid generating type_info for it. + FMT_NO_UNIQUE_ADDRESS Allocator alloc_; + + // Deallocate f_memory allocated by the buffer. + FMT_CONSTEXPR20 void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + static FMT_CONSTEXPR20 void grow(detail::buffer& buf, size_t size) { + detail::abort_fuzzing_if(size > 5000); + auto& self = static_cast(buf); + const size_t max_size = + std::allocator_traits::max_size(self.alloc_); + size_t old_capacity = buf.capacity(); + size_t new_capacity = old_capacity + old_capacity / 2; + if (size > new_capacity) + new_capacity = size; + else if (new_capacity > max_size) + new_capacity = max_of(size, max_size); + T* old_data = buf.data(); + T* new_data = self.alloc_.allocate(new_capacity); + // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). + detail::assume(buf.size() <= new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + memcpy(new_data, old_data, buf.size() * sizeof(T)); + self.set(new_data, new_capacity); + // deallocate must not throw according to the standard, but even if it does, + // the buffer already uses the new storage and will deallocate it in + // destructor. + if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity); + } + + public: + using value_type = T; + using const_reference = const T&; + + FMT_CONSTEXPR explicit basic_memory_buffer( + const Allocator& alloc = Allocator()) + : detail::buffer(grow), alloc_(alloc) { + this->set(store_, SIZE); + if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T()); + } + FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); } + + private: + // Move data from other to this buffer. + FMT_CONSTEXPR20 void move(basic_memory_buffer& other) { + alloc_ = std::move(other.alloc_); + T* data = other.data(); + size_t size = other.size(), capacity = other.capacity(); + if (data == other.store_) { + this->set(store_, capacity); + detail::copy(other.store_, other.store_ + size, store_); + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + other.clear(); + } + this->resize(size); + } + + public: + /// Constructs a `basic_memory_buffer` object moving the content of the other + /// object to it. + FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept + : detail::buffer(grow) { + move(other); + } + + /// Moves the content of the other `basic_memory_buffer` object to this one. + auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& { + FMT_ASSERT(this != &other, ""); + deallocate(); + move(other); + return *this; + } + + // Returns a copy of the allocator associated with this buffer. + auto get_allocator() const -> Allocator { return alloc_; } + + /// Resizes the buffer to contain `count` elements. If T is a POD type new + /// elements may not be initialized. + FMT_CONSTEXPR void resize(size_t count) { this->try_resize(count); } + + /// Increases the buffer capacity to `new_capacity`. + void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } + + using detail::buffer::append; + template + FMT_CONSTEXPR20 void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +using memory_buffer = basic_memory_buffer; + +template +FMT_NODISCARD auto to_string(const basic_memory_buffer& buf) + -> std::string { + auto size = buf.size(); + detail::assume(size < std::string().max_size()); + return {buf.data(), size}; +} + +// A writer to a buffered stream. It doesn't own the underlying stream. +class writer { + private: + detail::buffer* buf_; + + // We cannot create a file buffer in advance because any write to a FILE may + // invalidate it. + FILE* file_; + + public: + inline writer(FILE* f) : buf_(nullptr), file_(f) {} + inline writer(detail::buffer& buf) : buf_(&buf) {} + + /// Formats `args` according to specifications in `fmt` and writes the + /// output to the file. + template void print(format_string fmt, T&&... args) { + if (buf_) + fmt::format_to(appender(*buf_), fmt, std::forward(args)...); + else + fmt::print(file_, fmt, std::forward(args)...); + } +}; + +class string_buffer { + private: + std::string str_; + detail::container_buffer buf_; + + public: + inline string_buffer() : buf_(str_) {} + + inline operator writer() { return buf_; } + inline std::string& str() { return str_; } +}; + +template +struct is_contiguous> : std::true_type { +}; + +// Suppress a misleading warning in older versions of clang. +FMT_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables") + +/// An error reported from a formatting function. +class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error { + public: + using std::runtime_error::runtime_error; +}; + +class loc_value; + +FMT_END_EXPORT +namespace detail { +FMT_API auto write_console(int fd, string_view text) -> bool; +FMT_API void print(FILE*, string_view); +} // namespace detail + +namespace detail { +template struct fixed_string { + FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) { + detail::copy(static_cast(s), s + N, + data); + } + Char data[N] = {}; +}; + +// Converts a compile-time string to basic_string_view. +FMT_EXPORT template +constexpr auto compile_string_to_view(const Char (&s)[N]) + -> basic_string_view { + // Remove trailing NUL character if needed. Won't be present if this is used + // with a raw character array (i.e. not defined as a string). + return {s, N - (std::char_traits::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; +} +FMT_EXPORT template +constexpr auto compile_string_to_view(basic_string_view s) + -> basic_string_view { + return s; +} + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template ::value)> +constexpr auto is_negative(T value) -> bool { + return value < 0; +} +template ::value)> +constexpr auto is_negative(T) -> bool { + return false; +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template +using uint32_or_64_or_128_t = + conditional_t() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t() <= 64, uint64_t, uint128_t>>; +template +using uint64_or_128_t = conditional_t() <= 64, uint64_t, uint128_t>; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \ + (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \ + (factor) * 100000000, (factor) * 1000000000 + +// Converts value in the range [0, 100) to a string. +// GCC generates slightly better code when value is pointer-size. +inline auto digits2(size_t value) -> const char* { + // Align data since unaligned access may be slower when crossing a + // hardware-specific boundary. + alignas(2) static const char data[] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + return &data[value * 2]; +} + +template constexpr auto getsign(sign s) -> Char { + return static_cast(((' ' << 24) | ('+' << 16) | ('-' << 8)) >> + (static_cast(s) * 8)); +} + +template FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} +#if FMT_USE_INT128 +FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int { + return count_digits_fallback(n); +} +#endif + +#ifdef FMT_BUILTIN_CLZLL +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +inline auto do_count_digits(uint64_t n) -> int { + // This has comparable performance to the version by Kendall Willets + // (https://github.com/fmtlib/format-benchmark/blob/master/digits10) + // but uses smaller tables. + // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). + static constexpr uint8_t bsr2log10[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63]; + static constexpr const uint64_t zero_or_powers_of_10[] = { + 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + return t - (n < zero_or_powers_of_10[t]); +} +#endif + +// Returns the number of decimal digits in n. Leading zeros are not counted +// except for n == 0 in which case count_digits returns 1. +FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated() && !FMT_OPTIMIZE_SIZE) return do_count_digits(n); +#endif + return count_digits_fallback(n); +} + +// Counts the number of digits in n. BITS = log2(radix). +template +FMT_CONSTEXPR auto count_digits(UInt n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated() && num_bits() == 32) + return (FMT_BUILTIN_CLZ(static_cast(n) | 1) ^ 31) / BITS + 1; +#endif + // Lambda avoids unreachable code warnings from NVHPC. + return [](UInt m) { + int num_digits = 0; + do { + ++num_digits; + } while ((m >>= BITS) != 0); + return num_digits; + }(n); +} + +#ifdef FMT_BUILTIN_CLZ +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +FMT_INLINE auto do_count_digits(uint32_t n) -> int { +// An optimization by Kendall Willets from https://bit.ly/3uOIQrB. +// This increments the upper 32 bits (log10(T) - 1) when >= T is added. +# define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T) + static constexpr uint64_t table[] = { + FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8 + FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64 + FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512 + FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096 + FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k + FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k + FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k + FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M + FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M + FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M + FMT_INC(1000000000), FMT_INC(1000000000) // 4B + }; + auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31]; + return static_cast((n + inc) >> 32); +} +#endif + +// Optional version of count_digits for better performance on 32-bit platforms. +FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated() && !FMT_OPTIMIZE_SIZE) return do_count_digits(n); +#endif + return count_digits_fallback(n); +} + +template constexpr auto digits10() noexcept -> int { + return std::numeric_limits::digits10; +} +template <> constexpr auto digits10() noexcept -> int { return 38; } +template <> constexpr auto digits10() noexcept -> int { return 38; } + +template struct thousands_sep_result { + std::string grouping; + Char thousands_sep; +}; + +template +FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result; +template +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + auto result = thousands_sep_impl(loc); + return {result.grouping, Char(result.thousands_sep)}; +} +template <> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + return thousands_sep_impl(loc); +} + +template +FMT_API auto decimal_point_impl(locale_ref loc) -> Char; +template inline auto decimal_point(locale_ref loc) -> Char { + return Char(decimal_point_impl(loc)); +} +template <> inline auto decimal_point(locale_ref loc) -> wchar_t { + return decimal_point_impl(loc); +} + +#ifndef FMT_HEADER_ONLY +FMT_BEGIN_EXPORT +extern template FMT_API auto thousands_sep_impl(locale_ref) + -> thousands_sep_result; +extern template FMT_API auto thousands_sep_impl(locale_ref) + -> thousands_sep_result; +extern template FMT_API auto decimal_point_impl(locale_ref) -> char; +extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; +FMT_END_EXPORT +#endif // FMT_HEADER_ONLY + +// Compares two characters for equality. +template auto equal2(const Char* lhs, const char* rhs) -> bool { + return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); +} +inline auto equal2(const char* lhs, const char* rhs) -> bool { + return memcmp(lhs, rhs, 2) == 0; +} + +// Writes a two-digit value to out. +template +FMT_CONSTEXPR20 FMT_INLINE void write2digits(Char* out, size_t value) { + if (!is_constant_evaluated() && std::is_same::value && + !FMT_OPTIMIZE_SIZE) { + memcpy(out, digits2(value), 2); + return; + } + *out++ = static_cast('0' + value / 10); + *out = static_cast('0' + value % 10); +} + +// Formats a decimal unsigned integer value writing to out pointing to a buffer +// of specified size. The caller must ensure that the buffer is large enough. +template +FMT_CONSTEXPR20 auto do_format_decimal(Char* out, UInt value, int size) + -> Char* { + FMT_ASSERT(size >= count_digits(value), "invalid digit count"); + unsigned n = to_unsigned(size); + while (value >= 100) { + // Integer division is slow so do it for a group of two digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + n -= 2; + write2digits(out + n, static_cast(value % 100)); + value /= 100; + } + if (value >= 10) { + n -= 2; + write2digits(out + n, static_cast(value)); + } else { + out[--n] = static_cast('0' + value); + } + return out + n; +} + +template +FMT_CONSTEXPR FMT_INLINE auto format_decimal(Char* out, UInt value, + int num_digits) -> Char* { + do_format_decimal(out, value, num_digits); + return out + num_digits; +} + +template >::value)> +FMT_CONSTEXPR auto format_decimal(OutputIt out, UInt value, int num_digits) + -> OutputIt { + if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { + do_format_decimal(ptr, value, num_digits); + return out; + } + // Buffer is large enough to hold all digits (digits10 + 1). + char buffer[digits10() + 1]; + if (is_constant_evaluated()) fill_n(buffer, sizeof(buffer), '\0'); + do_format_decimal(buffer, value, num_digits); + return copy_noinline(buffer, buffer + num_digits, out); +} + +template +FMT_CONSTEXPR auto do_format_base2e(int base_bits, Char* out, UInt value, + int size, bool upper = false) -> Char* { + out += size; + do { + const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + unsigned digit = static_cast(value & ((1 << base_bits) - 1)); + *--out = static_cast(base_bits < 4 ? static_cast('0' + digit) + : digits[digit]); + } while ((value >>= base_bits) != 0); + return out; +} + +// Formats an unsigned integer in the power of two base (binary, octal, hex). +template +FMT_CONSTEXPR auto format_base2e(int base_bits, Char* out, UInt value, + int num_digits, bool upper = false) -> Char* { + do_format_base2e(base_bits, out, value, num_digits, upper); + return out + num_digits; +} + +template ::value)> +FMT_CONSTEXPR inline auto format_base2e(int base_bits, OutputIt out, UInt value, + int num_digits, bool upper = false) + -> OutputIt { + if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { + format_base2e(base_bits, ptr, value, num_digits, upper); + return out; + } + // Make buffer large enough for any base. + char buffer[num_bits()]; + if (is_constant_evaluated()) fill_n(buffer, sizeof(buffer), '\0'); + format_base2e(base_bits, buffer, value, num_digits, upper); + return detail::copy_noinline(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + basic_memory_buffer buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + inline operator basic_string_view() const { + return {&buffer_[0], size()}; + } + inline auto size() const -> size_t { return buffer_.size() - 1; } + inline auto c_str() const -> const wchar_t* { return &buffer_[0]; } + inline auto str() const -> std::wstring { return {&buffer_[0], size()}; } +}; + +enum class to_utf8_error_policy { abort, replace }; + +// A converter from UTF-16/UTF-32 (host endian) to UTF-8. +template class to_utf8 { + private: + Buffer buffer_; + + public: + to_utf8() {} + explicit to_utf8(basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) { + static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4, + "Expect utf16 or utf32"); + if (!convert(s, policy)) + FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16" + : "invalid utf32")); + } + operator string_view() const { return string_view(&buffer_[0], size()); } + auto size() const -> size_t { return buffer_.size() - 1; } + auto c_str() const -> const char* { return &buffer_[0]; } + auto str() const -> std::string { return std::string(&buffer_[0], size()); } + + // Performs conversion returning a bool instead of throwing exception on + // conversion error. This method may still throw in case of f_memory allocation + // error. + auto convert(basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) + -> bool { + if (!convert(buffer_, s, policy)) return false; + buffer_.push_back(0); + return true; + } + static auto convert(Buffer& buf, basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) + -> bool { + for (auto p = s.begin(); p != s.end(); ++p) { + uint32_t c = static_cast(*p); + if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) { + // Handle a surrogate pair. + ++p; + if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) { + if (policy == to_utf8_error_policy::abort) return false; + buf.append(string_view("\xEF\xBF\xBD")); + --p; + continue; + } else { + c = (c << 10) + static_cast(*p) - 0x35fdc00; + } + } + if (c < 0x80) { + buf.push_back(static_cast(c)); + } else if (c < 0x800) { + buf.push_back(static_cast(0xc0 | (c >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { + buf.push_back(static_cast(0xe0 | (c >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if (c >= 0x10000 && c <= 0x10ffff) { + buf.push_back(static_cast(0xf0 | (c >> 18))); + buf.push_back(static_cast(0x80 | ((c & 0x3ffff) >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else { + return false; + } + } + return true; + } +}; + +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +inline auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return {static_cast(p >> 64), static_cast(p)}; +#elif defined(_MSC_VER) && defined(_M_X64) + auto hi = uint64_t(); + auto lo = _umul128(x, y, &hi); + return {hi, lo}; +#else + const uint64_t mask = static_cast(max_value()); + + uint64_t a = x >> 32; + uint64_t b = x & mask; + uint64_t c = y >> 32; + uint64_t d = y & mask; + + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + + uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); + + return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), + (intermediate << 32) + (bd & mask)}; +#endif +} + +namespace dragonbox { +// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from +// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1. +inline auto floor_log10_pow2(int e) noexcept -> int { + FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent"); + static_assert((-1 >> 1) == -1, "right shift is not arithmetic"); + return (e * 315653) >> 20; +} + +inline auto floor_log2_pow10(int e) noexcept -> int { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + return (e * 1741647) >> 19; +} + +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return static_cast(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept + -> uint128_fallback { + uint128_fallback r = umul128(x, y.high()); + r += umul128_upper64(x, y.low()); + return r; +} + +FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback; + +// Type-specific information that Dragonbox uses. +template struct float_info; + +template <> struct float_info { + using carrier_uint = uint32_t; + static const int exponent_bits = 8; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; +}; + +template <> struct float_info { + using carrier_uint = uint64_t; + static const int exponent_bits = 11; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 341; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; +}; + +// An 80- or 128-bit floating point number. +template +struct float_info::digits == 64 || + std::numeric_limits::digits == 113 || + is_float128::value>> { + using carrier_uint = detail::uint128_t; + static const int exponent_bits = 15; +}; + +// A double-double floating point number. +template +struct float_info::value>> { + using carrier_uint = detail::uint128_t; +}; + +template struct decimal_fp { + using significand_type = typename float_info::carrier_uint; + significand_type significand; + int exponent; +}; + +template FMT_API auto to_decimal(T x) noexcept -> decimal_fp; +} // namespace dragonbox + +// Returns true iff Float has the implicit bit which is not stored. +template constexpr auto has_implicit_bit() -> bool { + // An 80-bit FP number has a 64-bit significand an no implicit bit. + return std::numeric_limits::digits != 64; +} + +// Returns the number of significand bits stored in Float. The implicit bit is +// not counted since it is not stored. +template constexpr auto num_significand_bits() -> int { + // std::numeric_limits may not support __float128. + return is_float128() ? 112 + : (std::numeric_limits::digits - + (has_implicit_bit() ? 1 : 0)); +} + +template +constexpr auto exponent_mask() -> + typename dragonbox::float_info::carrier_uint { + using float_uint = typename dragonbox::float_info::carrier_uint; + return ((float_uint(1) << dragonbox::float_info::exponent_bits) - 1) + << num_significand_bits(); +} +template constexpr auto exponent_bias() -> int { + // std::numeric_limits may not support __float128. + return is_float128() ? 16383 + : std::numeric_limits::max_exponent - 1; +} + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template +FMT_CONSTEXPR auto write_exponent(int exp, OutputIt out) -> OutputIt { + FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); + if (exp < 0) { + *out++ = static_cast('-'); + exp = -exp; + } else { + *out++ = static_cast('+'); + } + auto uexp = static_cast(exp); + if (is_constant_evaluated()) { + if (uexp < 10) *out++ = '0'; + return format_decimal(out, uexp, count_digits(uexp)); + } + if (uexp >= 100u) { + const char* top = digits2(uexp / 100); + if (uexp >= 1000u) *out++ = static_cast(top[0]); + *out++ = static_cast(top[1]); + uexp %= 100; + } + const char* d = digits2(uexp); + *out++ = static_cast(d[0]); + *out++ = static_cast(d[1]); + return out; +} + +// A floating-point number f * pow(2, e) where F is an unsigned type. +template struct basic_fp { + F f; + int e; + + static constexpr const int num_significand_bits = + static_cast(sizeof(F) * num_bits()); + + constexpr basic_fp() : f(0), e(0) {} + constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 floating-point number. + template FMT_CONSTEXPR basic_fp(Float n) { assign(n); } + + // Assigns n to this and return true iff predecessor is closer than successor. + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::digits <= 113, "unsupported FP"); + // Assume Float is in the format [sign][exponent][significand]. + using carrier_uint = typename dragonbox::float_info::carrier_uint; + const auto num_float_significand_bits = + detail::num_significand_bits(); + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + const auto significand_mask = implicit_bit - 1; + auto u = bit_cast(n); + f = static_cast(u & significand_mask); + auto biased_e = static_cast((u & exponent_mask()) >> + num_float_significand_bits); + // The predecessor is closer if n is a normalized power of 2 (f == 0) + // other than the smallest normalized number (biased_e > 1). + auto is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e == 0) + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + else if (has_implicit_bit()) + f += static_cast(implicit_bit); + e = biased_e - exponent_bias() - num_float_significand_bits; + if (!has_implicit_bit()) ++e; + return is_predecessor_closer; + } + + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::is_iec559, "unsupported FP"); + return assign(static_cast(n)); + } +}; + +using fp = basic_fp; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template +FMT_CONSTEXPR auto normalize(basic_fp value) -> basic_fp { + // Handle subnormals. + const auto implicit_bit = F(1) << num_significand_bits(); + const auto shifted_implicit_bit = implicit_bit << SHIFT; + while ((value.f & shifted_implicit_bit) == 0) { + value.f <<= 1; + --value.e; + } + // Subtract 1 to account for hidden bit. + const auto offset = basic_fp::num_significand_bits - + num_significand_bits() - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast(product >> 64); + return (static_cast(product) & (1ULL << 63)) != 0 ? f + 1 : f; +#else + // Multiply 32-bit parts of significands. + uint64_t mask = (1ULL << 32) - 1; + uint64_t a = lhs >> 32, b = lhs & mask; + uint64_t c = rhs >> 32, d = rhs & mask; + uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; + // Compute mid 64-bit of result and round. + uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); + return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); +#endif +} + +FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp { + return {multiply(x.f, y.f), x.e + y.e + 64}; +} + +template () == num_bits()> +using convert_float_result = + conditional_t::value || doublish, double, T>; + +template +constexpr auto convert_float(T value) -> convert_float_result { + return static_cast>(value); +} + +template +FMT_CONSTEXPR FMT_NOINLINE auto fill(OutputIt it, size_t n, + const basic_specs& specs) -> OutputIt { + auto fill_size = specs.fill_size(); + if (fill_size == 1) return detail::fill_n(it, n, specs.fill_unit()); + if (const Char* data = specs.fill()) { + for (size_t i = 0; i < n; ++i) it = copy(data, data + fill_size, it); + } + return it; +} + +// Writes the output of f, padded according to format specifications in specs. +// size: output size in code units. +// width: output display width in (terminal) column positions. +template +FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, + size_t size, size_t width, F&& f) -> OutputIt { + static_assert(default_align == align::left || default_align == align::right, + ""); + unsigned spec_width = to_unsigned(specs.width); + size_t padding = spec_width > width ? spec_width - width : 0; + // Shifts are encoded as string literals because static constexpr is not + // supported in constexpr functions. + auto* shifts = + default_align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01"; + size_t left_padding = padding >> shifts[static_cast(specs.align())]; + size_t right_padding = padding - left_padding; + auto it = reserve(out, size + padding * specs.fill_size()); + if (left_padding != 0) it = fill(it, left_padding, specs); + it = f(it); + if (right_padding != 0) it = fill(it, right_padding, specs); + return base_iterator(out, it); +} + +template +constexpr auto write_padded(OutputIt out, const format_specs& specs, + size_t size, F&& f) -> OutputIt { + return write_padded(out, specs, size, size, f); +} + +template +FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, + const format_specs& specs = {}) -> OutputIt { + return write_padded( + out, specs, bytes.size(), [bytes](reserve_iterator it) { + const char* data = bytes.data(); + return copy(data, data + bytes.size(), it); + }); +} + +template +auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs) + -> OutputIt { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + auto write = [=](reserve_iterator it) { + *it++ = static_cast('0'); + *it++ = static_cast('x'); + return format_base2e(4, it, value, num_digits); + }; + return specs ? write_padded(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +// Returns true iff the code point cp is printable. +FMT_API auto is_printable(uint32_t cp) -> bool; + +inline auto needs_escape(uint32_t cp) -> bool { + if (cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\') return true; + if (const_check(FMT_OPTIMIZE_SIZE > 1)) return false; + return !is_printable(cp); +} + +template struct find_escape_result { + const Char* begin; + const Char* end; + uint32_t cp; +}; + +template +auto find_escape(const Char* begin, const Char* end) + -> find_escape_result { + for (; begin != end; ++begin) { + uint32_t cp = static_cast>(*begin); + if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue; + if (needs_escape(cp)) return {begin, begin + 1, cp}; + } + return {begin, nullptr, 0}; +} + +inline auto find_escape(const char* begin, const char* end) + -> find_escape_result { + if (const_check(!use_utf8)) return find_escape(begin, end); + auto result = find_escape_result{end, nullptr, 0}; + for_each_codepoint(string_view(begin, to_unsigned(end - begin)), + [&](uint32_t cp, string_view sv) { + if (needs_escape(cp)) { + result = {sv.begin(), sv.end(), cp}; + return false; + } + return true; + }); + return result; +} + +template +auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt { + *out++ = static_cast('\\'); + *out++ = static_cast(prefix); + Char buf[width]; + fill_n(buf, width, static_cast('0')); + format_base2e(4, buf, cp, width); + return copy(buf, buf + width, out); +} + +template +auto write_escaped_cp(OutputIt out, const find_escape_result& escape) + -> OutputIt { + auto c = static_cast(escape.cp); + switch (escape.cp) { + case '\n': + *out++ = static_cast('\\'); + c = static_cast('n'); + break; + case '\r': + *out++ = static_cast('\\'); + c = static_cast('r'); + break; + case '\t': + *out++ = static_cast('\\'); + c = static_cast('t'); + break; + case '"': FMT_FALLTHROUGH; + case '\'': FMT_FALLTHROUGH; + case '\\': *out++ = static_cast('\\'); break; + default: + if (escape.cp < 0x100) return write_codepoint<2, Char>(out, 'x', escape.cp); + if (escape.cp < 0x10000) + return write_codepoint<4, Char>(out, 'u', escape.cp); + if (escape.cp < 0x110000) + return write_codepoint<8, Char>(out, 'U', escape.cp); + for (Char escape_char : basic_string_view( + escape.begin, to_unsigned(escape.end - escape.begin))) { + out = write_codepoint<2, Char>(out, 'x', + static_cast(escape_char) & 0xFF); + } + return out; + } + *out++ = c; + return out; +} + +template +auto write_escaped_string(OutputIt out, basic_string_view str) + -> OutputIt { + *out++ = static_cast('"'); + auto begin = str.begin(), end = str.end(); + do { + auto escape = find_escape(begin, end); + out = copy(begin, escape.begin, out); + begin = escape.end; + if (!begin) break; + out = write_escaped_cp(out, escape); + } while (begin != end); + *out++ = static_cast('"'); + return out; +} + +template +auto write_escaped_char(OutputIt out, Char v) -> OutputIt { + Char v_array[1] = {v}; + *out++ = static_cast('\''); + if ((needs_escape(static_cast(v)) && v != static_cast('"')) || + v == static_cast('\'')) { + out = write_escaped_cp(out, + find_escape_result{v_array, v_array + 1, + static_cast(v)}); + } else { + *out++ = v; + } + *out++ = static_cast('\''); + return out; +} + +template +FMT_CONSTEXPR auto write_char(OutputIt out, Char value, + const format_specs& specs) -> OutputIt { + bool is_debug = specs.type() == presentation_type::debug; + return write_padded(out, specs, 1, [=](reserve_iterator it) { + if (is_debug) return write_escaped_char(it, value); + *it++ = value; + return it; + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs& specs, + locale_ref loc = {}) -> OutputIt { + // char is formatted as unsigned char for consistency across platforms. + using unsigned_type = + conditional_t::value, unsigned char, unsigned>; + return check_char_specs(specs) + ? write_char(out, value, specs) + : write(out, static_cast(value), specs, loc); +} + +template class digit_grouping { + private: + std::string grouping_; + std::basic_string thousands_sep_; + + struct next_state { + std::string::const_iterator group; + int pos; + }; + auto initial_state() const -> next_state { return {grouping_.begin(), 0}; } + + // Returns the next digit group separator position. + auto next(next_state& state) const -> int { + if (thousands_sep_.empty()) return max_value(); + if (state.group == grouping_.end()) return state.pos += grouping_.back(); + if (*state.group <= 0 || *state.group == max_value()) + return max_value(); + state.pos += *state.group++; + return state.pos; + } + + public: + template ::value)> + explicit digit_grouping(Locale loc, bool localized = true) { + if (!localized) return; + auto sep = thousands_sep(loc); + grouping_ = sep.grouping; + if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep); + } + digit_grouping(std::string grouping, std::basic_string sep) + : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {} + + auto has_separator() const -> bool { return !thousands_sep_.empty(); } + + auto count_separators(int num_digits) const -> int { + int count = 0; + auto state = initial_state(); + while (num_digits > next(state)) ++count; + return count; + } + + // Applies grouping to digits and write the output to out. + template + auto apply(Out out, basic_string_view digits) const -> Out { + auto num_digits = static_cast(digits.size()); + auto separators = basic_memory_buffer(); + separators.push_back(0); + auto state = initial_state(); + while (int i = next(state)) { + if (i >= num_digits) break; + separators.push_back(i); + } + for (int i = 0, sep_index = static_cast(separators.size() - 1); + i < num_digits; ++i) { + if (num_digits - i == separators[sep_index]) { + out = copy(thousands_sep_.data(), + thousands_sep_.data() + thousands_sep_.size(), out); + --sep_index; + } + *out++ = static_cast(digits[to_unsigned(i)]); + } + return out; + } +}; + +FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { + prefix |= prefix != 0 ? value << 8 : value; + prefix += (1u + (value > 0xff ? 1 : 0)) << 24; +} + +// Writes a decimal integer with digit grouping. +template +auto write_int(OutputIt out, UInt value, unsigned prefix, + const format_specs& specs, const digit_grouping& grouping) + -> OutputIt { + static_assert(std::is_same, UInt>::value, ""); + int num_digits = 0; + auto buffer = memory_buffer(); + switch (specs.type()) { + default: FMT_ASSERT(false, ""); FMT_FALLTHROUGH; + case presentation_type::none: + case presentation_type::dec: + num_digits = count_digits(value); + format_decimal(appender(buffer), value, num_digits); + break; + case presentation_type::hex: + if (specs.alt()) + prefix_append(prefix, unsigned(specs.upper() ? 'X' : 'x') << 8 | '0'); + num_digits = count_digits<4>(value); + format_base2e(4, appender(buffer), value, num_digits, specs.upper()); + break; + case presentation_type::oct: + num_digits = count_digits<3>(value); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + if (specs.alt() && specs.precision <= num_digits && value != 0) + prefix_append(prefix, '0'); + format_base2e(3, appender(buffer), value, num_digits); + break; + case presentation_type::bin: + if (specs.alt()) + prefix_append(prefix, unsigned(specs.upper() ? 'B' : 'b') << 8 | '0'); + num_digits = count_digits<1>(value); + format_base2e(1, appender(buffer), value, num_digits); + break; + case presentation_type::chr: + return write_char(out, static_cast(value), specs); + } + + unsigned size = (prefix != 0 ? prefix >> 24 : 0) + to_unsigned(num_digits) + + to_unsigned(grouping.count_separators(num_digits)); + return write_padded( + out, specs, size, size, [&](reserve_iterator it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + return grouping.apply(it, string_view(buffer.data(), buffer.size())); + }); +} + +#if FMT_USE_LOCALE +// Writes a localized value. +FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs, + locale_ref loc) -> bool; +#endif +template +inline auto write_loc(OutputIt, const loc_value&, const format_specs&, + locale_ref) -> bool { + return false; +} + +template struct write_int_arg { + UInt abs_value; + unsigned prefix; +}; + +template +FMT_CONSTEXPR auto make_write_int_arg(T value, sign s) + -> write_int_arg> { + auto prefix = 0u; + auto abs_value = static_cast>(value); + if (is_negative(value)) { + prefix = 0x01000000 | '-'; + abs_value = 0 - abs_value; + } else { + constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', + 0x1000000u | ' '}; + prefix = prefixes[static_cast(s)]; + } + return {abs_value, prefix}; +} + +template struct loc_writer { + basic_appender out; + const format_specs& specs; + std::basic_string sep; + std::string grouping; + std::basic_string decimal_point; + + template ::value)> + auto operator()(T value) -> bool { + auto arg = make_write_int_arg(value, specs.sign()); + write_int(out, static_cast>(arg.abs_value), arg.prefix, + specs, digit_grouping(grouping, sep)); + return true; + } + + template ::value)> + auto operator()(T) -> bool { + return false; + } +}; + +// Size and padding computation separate from write_int to avoid template bloat. +struct size_padding { + unsigned size; + unsigned padding; + + FMT_CONSTEXPR size_padding(int num_digits, unsigned prefix, + const format_specs& specs) + : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { + if (specs.align() == align::numeric) { + auto width = to_unsigned(specs.width); + if (width > size) { + padding = width - size; + size = width; + } + } else if (specs.precision > num_digits) { + size = (prefix >> 24) + to_unsigned(specs.precision); + padding = to_unsigned(specs.precision - num_digits); + } + } +}; + +template +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg arg, + const format_specs& specs) -> OutputIt { + static_assert(std::is_same>::value, ""); + + constexpr int buffer_size = num_bits(); + char buffer[buffer_size]; + if (is_constant_evaluated()) fill_n(buffer, buffer_size, '\0'); + const char* begin = nullptr; + const char* end = buffer + buffer_size; + + auto abs_value = arg.abs_value; + auto prefix = arg.prefix; + switch (specs.type()) { + default: FMT_ASSERT(false, ""); FMT_FALLTHROUGH; + case presentation_type::none: + case presentation_type::dec: + begin = do_format_decimal(buffer, abs_value, buffer_size); + break; + case presentation_type::hex: + begin = do_format_base2e(4, buffer, abs_value, buffer_size, specs.upper()); + if (specs.alt()) + prefix_append(prefix, unsigned(specs.upper() ? 'X' : 'x') << 8 | '0'); + break; + case presentation_type::oct: { + begin = do_format_base2e(3, buffer, abs_value, buffer_size); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + auto num_digits = end - begin; + if (specs.alt() && specs.precision <= num_digits && abs_value != 0) + prefix_append(prefix, '0'); + break; + } + case presentation_type::bin: + begin = do_format_base2e(1, buffer, abs_value, buffer_size); + if (specs.alt()) + prefix_append(prefix, unsigned(specs.upper() ? 'B' : 'b') << 8 | '0'); + break; + case presentation_type::chr: + return write_char(out, static_cast(abs_value), specs); + } + + // Write an integer in the format + // + // prefix contains chars in three lower bytes and the size in the fourth byte. + int num_digits = static_cast(end - begin); + // Slightly faster check for specs.width == 0 && specs.precision == -1. + if ((specs.width | (specs.precision + 1)) == 0) { + auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24)); + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + return base_iterator(out, copy(begin, end, it)); + } + auto sp = size_padding(num_digits, prefix, specs); + unsigned padding = sp.padding; + return write_padded( + out, specs, sp.size, [=](reserve_iterator it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + it = detail::fill_n(it, padding, static_cast('0')); + return copy(begin, end, it); + }); +} + +template +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, + write_int_arg arg, + const format_specs& specs) + -> OutputIt { + return write_int(out, arg, specs); +} + +template ::value && + !std::is_same::value && + !std::is_same::value)> +FMT_CONSTEXPR FMT_INLINE auto write(basic_appender out, T value, + const format_specs& specs, locale_ref loc) + -> basic_appender { + if (specs.localized() && write_loc(out, value, specs, loc)) return out; + return write_int_noinline(out, make_write_int_arg(value, specs.sign()), + specs); +} + +// An inlined version of write used in format string compilation. +template ::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const format_specs& specs, locale_ref loc) + -> OutputIt { + if (specs.localized() && write_loc(out, value, specs, loc)) return out; + return write_int(out, make_write_int_arg(value, specs.sign()), specs); +} + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, + const format_specs& specs) -> OutputIt { + auto data = s.data(); + auto size = s.size(); + if (specs.precision >= 0 && to_unsigned(specs.precision) < size) + size = code_point_index(s, to_unsigned(specs.precision)); + + bool is_debug = specs.type() == presentation_type::debug; + if (is_debug) { + auto buf = counting_buffer(); + write_escaped_string(basic_appender(buf), s); + size = buf.count(); + } + + size_t width = 0; + if (specs.width != 0) { + width = + is_debug ? size : compute_width(basic_string_view(data, size)); + } + return write_padded( + out, specs, size, width, [=](reserve_iterator it) { + return is_debug ? write_escaped_string(it, s) + : copy(data, data + size, it); + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, + const format_specs& specs, locale_ref) -> OutputIt { + return write(out, s, specs); +} +template +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, const format_specs& specs, + locale_ref) -> OutputIt { + if (specs.type() == presentation_type::pointer) + return write_ptr(out, bit_cast(s), &specs); + if (!s) report_error("string pointer is null"); + return write(out, basic_string_view(s), specs, {}); +} + +template ::value && + !std::is_same::value && + !std::is_same::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + auto abs_value = static_cast>(value); + bool negative = is_negative(value); + // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. + if (negative) abs_value = ~abs_value + 1; + int num_digits = count_digits(abs_value); + auto size = (negative ? 1 : 0) + static_cast(num_digits); + if (auto ptr = to_pointer(out, size)) { + if (negative) *ptr++ = static_cast('-'); + format_decimal(ptr, abs_value, num_digits); + return out; + } + if (negative) *out++ = static_cast('-'); + return format_decimal(out, abs_value, num_digits); +} + +template +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, + format_specs& specs) -> const Char* { + FMT_ASSERT(begin != end, ""); + auto alignment = align::none; + auto p = begin + code_point_length(begin); + if (end - p <= 0) p = begin; + for (;;) { + switch (to_ascii(*p)) { + case '<': alignment = align::left; break; + case '>': alignment = align::right; break; + case '^': alignment = align::center; break; + } + if (alignment != align::none) { + if (p != begin) { + auto c = *begin; + if (c == '}') return begin; + if (c == '{') { + report_error("invalid fill character '{'"); + return begin; + } + specs.set_fill(basic_string_view(begin, to_unsigned(p - begin))); + begin = p + 1; + } else { + ++begin; + } + break; + } else if (p == begin) { + break; + } + p = begin; + } + specs.set_align(alignment); + return begin; +} + +template +FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, + format_specs specs, sign s) -> OutputIt { + auto str = + isnan ? (specs.upper() ? "NAN" : "nan") : (specs.upper() ? "INF" : "inf"); + constexpr size_t str_size = 3; + auto size = str_size + (s != sign::none ? 1 : 0); + // Replace '0'-padding with space for non-finite values. + const bool is_zero_fill = + specs.fill_size() == 1 && specs.fill_unit() == '0'; + if (is_zero_fill) specs.set_fill(' '); + return write_padded(out, specs, size, + [=](reserve_iterator it) { + if (s != sign::none) + *it++ = detail::getsign(s); + return copy(str, str + str_size, it); + }); +} + +// A decimal floating-point number significand * pow(10, exp). +struct big_decimal_fp { + const char* significand; + int significand_size; + int exponent; +}; + +constexpr auto get_significand_size(const big_decimal_fp& f) -> int { + return f.significand_size; +} +template +inline auto get_significand_size(const dragonbox::decimal_fp& f) -> int { + return count_digits(f.significand); +} + +template +constexpr auto write_significand(OutputIt out, const char* significand, + int significand_size) -> OutputIt { + return copy(significand, significand + significand_size, out); +} +template +inline auto write_significand(OutputIt out, UInt significand, + int significand_size) -> OutputIt { + return format_decimal(out, significand, significand_size); +} +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int exponent, + const Grouping& grouping) -> OutputIt { + if (!grouping.has_separator()) { + out = write_significand(out, significand, significand_size); + return detail::fill_n(out, exponent, static_cast('0')); + } + auto buffer = memory_buffer(); + write_significand(appender(buffer), significand, significand_size); + detail::fill_n(appender(buffer), exponent, '0'); + return grouping.apply(out, string_view(buffer.data(), buffer.size())); +} + +template ::value)> +inline auto write_significand(Char* out, UInt significand, int significand_size, + int integral_size, Char decimal_point) -> Char* { + if (!decimal_point) return format_decimal(out, significand, significand_size); + out += significand_size + 1; + Char* end = out; + int floating_size = significand_size - integral_size; + for (int i = floating_size / 2; i > 0; --i) { + out -= 2; + write2digits(out, static_cast(significand % 100)); + significand /= 100; + } + if (floating_size % 2 != 0) { + *--out = static_cast('0' + significand % 10); + significand /= 10; + } + *--out = decimal_point; + format_decimal(out - integral_size, significand, integral_size); + return end; +} + +template >::value)> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + // Buffer is large enough to hold digits (digits10 + 1) and a decimal point. + Char buffer[digits10() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_noinline(buffer, end, out); +} + +template +FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + out = detail::copy_noinline(significand, significand + integral_size, + out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_noinline(significand + integral_size, + significand + significand_size, out); +} + +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int integral_size, + Char decimal_point, + const Grouping& grouping) -> OutputIt { + if (!grouping.has_separator()) { + return write_significand(out, significand, significand_size, integral_size, + decimal_point); + } + auto buffer = basic_memory_buffer(); + write_significand(basic_appender(buffer), significand, significand_size, + integral_size, decimal_point); + grouping.apply( + out, basic_string_view(buffer.data(), to_unsigned(integral_size))); + return detail::copy_noinline(buffer.data() + integral_size, + buffer.end(), out); +} + +template > +FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, + const format_specs& specs, sign s, + int exp_upper, locale_ref loc) -> OutputIt { + auto significand = f.significand; + int significand_size = get_significand_size(f); + const Char zero = static_cast('0'); + size_t size = to_unsigned(significand_size) + (s != sign::none ? 1 : 0); + using iterator = reserve_iterator; + + Char decimal_point = specs.localized() ? detail::decimal_point(loc) + : static_cast('.'); + + int output_exp = f.exponent + significand_size - 1; + auto use_exp_format = [=]() { + if (specs.type() == presentation_type::exp) return true; + if (specs.type() == presentation_type::fixed) return false; + // Use the fixed notation if the exponent is in [exp_lower, exp_upper), + // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. + const int exp_lower = -4; + return output_exp < exp_lower || + output_exp >= (specs.precision > 0 ? specs.precision : exp_upper); + }; + if (use_exp_format()) { + int num_zeros = 0; + if (specs.alt()) { + num_zeros = specs.precision - significand_size; + if (num_zeros < 0) num_zeros = 0; + size += to_unsigned(num_zeros); + } else if (significand_size == 1) { + decimal_point = Char(); + } + auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; + int exp_digits = 2; + if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; + + size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); + char exp_char = specs.upper() ? 'E' : 'e'; + auto write = [=](iterator it) { + if (s != sign::none) *it++ = detail::getsign(s); + // Insert a decimal point after the first digit and add an exponent. + it = write_significand(it, significand, significand_size, 1, + decimal_point); + if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); + *it++ = static_cast(exp_char); + return write_exponent(output_exp, it); + }; + return specs.width > 0 + ? write_padded(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = f.exponent + significand_size; + if (f.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(f.exponent); + int num_zeros = specs.precision - exp; + abort_fuzzing_if(num_zeros > 5000); + if (specs.alt()) { + ++size; + if (num_zeros <= 0 && specs.type() != presentation_type::fixed) + num_zeros = 0; + if (num_zeros > 0) size += to_unsigned(num_zeros); + } + auto grouping = Grouping(loc, specs.localized()); + size += to_unsigned(grouping.count_separators(exp)); + return write_padded(out, specs, size, [&](iterator it) { + if (s != sign::none) *it++ = detail::getsign(s); + it = write_significand(it, significand, significand_size, + f.exponent, grouping); + if (!specs.alt()) return it; + *it++ = decimal_point; + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } else if (exp > 0) { + // 1234e-2 -> 12.34[0+] + int num_zeros = specs.alt() ? specs.precision - significand_size : 0; + size += 1 + static_cast(max_of(num_zeros, 0)); + auto grouping = Grouping(loc, specs.localized()); + size += to_unsigned(grouping.count_separators(exp)); + return write_padded(out, specs, size, [&](iterator it) { + if (s != sign::none) *it++ = detail::getsign(s); + it = write_significand(it, significand, significand_size, exp, + decimal_point, grouping); + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } + // 1234e-6 -> 0.001234 + int num_zeros = -exp; + if (significand_size == 0 && specs.precision >= 0 && + specs.precision < num_zeros) { + num_zeros = specs.precision; + } + bool pointy = num_zeros != 0 || significand_size != 0 || specs.alt(); + size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros); + return write_padded(out, specs, size, [&](iterator it) { + if (s != sign::none) *it++ = detail::getsign(s); + *it++ = zero; + if (!pointy) return it; + *it++ = decimal_point; + it = detail::fill_n(it, num_zeros, zero); + return write_significand(it, significand, significand_size); + }); +} + +template class fallback_digit_grouping { + public: + constexpr fallback_digit_grouping(locale_ref, bool) {} + + constexpr auto has_separator() const -> bool { return false; } + + constexpr auto count_separators(int) const -> int { return 0; } + + template + constexpr auto apply(Out out, basic_string_view) const -> Out { + return out; + } +}; + +template +FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, + const format_specs& specs, sign s, + int exp_upper, locale_ref loc) -> OutputIt { + if (is_constant_evaluated()) { + return do_write_float>(out, f, specs, s, + exp_upper, loc); + } else { + return do_write_float(out, f, specs, s, exp_upper, loc); + } +} + +template constexpr auto isnan(T value) -> bool { + return value != value; // std::isnan doesn't support __float128. +} + +template +struct has_isfinite : std::false_type {}; + +template +struct has_isfinite> + : std::true_type {}; + +template ::value&& has_isfinite::value)> +FMT_CONSTEXPR20 auto isfinite(T value) -> bool { + constexpr T inf = T(std::numeric_limits::infinity()); + if (is_constant_evaluated()) + return !detail::isnan(value) && value < inf && value > -inf; + return std::isfinite(value); +} +template ::value)> +FMT_CONSTEXPR auto isfinite(T value) -> bool { + T inf = T(std::numeric_limits::infinity()); + // std::isfinite doesn't support __float128. + return !detail::isnan(value) && value < inf && value > -inf; +} + +template ::value)> +FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { + if (is_constant_evaluated()) { +#ifdef __cpp_if_constexpr + if constexpr (std::numeric_limits::is_iec559) { + auto bits = detail::bit_cast(static_cast(value)); + return (bits >> (num_bits() - 1)) != 0; + } +#endif + } + return std::signbit(static_cast(value)); +} + +inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) { + // Adjust fixed precision by exponent because it is relative to decimal + // point. + if (exp10 > 0 && precision > max_value() - exp10) + FMT_THROW(format_error("number is too big")); + precision += exp10; +} + +class bigint { + private: + // A bigint is a number in the form bigit_[N - 1] ... bigit_[0] * 32^exp_. + using bigit = uint32_t; // A big digit. + using double_bigit = uint64_t; + enum { bigit_bits = num_bits() }; + enum { bigits_capacity = 32 }; + basic_memory_buffer bigits_; + int exp_; + + friend struct formatter; + + FMT_CONSTEXPR auto get_bigit(int i) const -> bigit { + return i >= exp_ && i < num_bigits() ? bigits_[i - exp_] : 0; + } + + FMT_CONSTEXPR void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = double_bigit(bigits_[index]) - other - borrow; + bigits_[index] = static_cast(result); + borrow = static_cast(result >> (bigit_bits * 2 - 1)); + } + + FMT_CONSTEXPR void remove_leading_zeros() { + int num_bigits = static_cast(bigits_.size()) - 1; + while (num_bigits > 0 && bigits_[num_bigits] == 0) --num_bigits; + bigits_.resize(to_unsigned(num_bigits + 1)); + } + + // Computes *this -= other assuming aligned bigints and *this >= other. + FMT_CONSTEXPR void subtract_aligned(const bigint& other) { + FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); + FMT_ASSERT(compare(*this, other) >= 0, ""); + bigit borrow = 0; + int i = other.exp_ - exp_; + for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) + subtract_bigits(i, other.bigits_[j], borrow); + if (borrow != 0) subtract_bigits(i, 0, borrow); + FMT_ASSERT(borrow == 0, ""); + remove_leading_zeros(); + } + + FMT_CONSTEXPR void multiply(uint32_t value) { + bigit carry = 0; + const double_bigit wide_value = value; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * wide_value + carry; + bigits_[i] = static_cast(result); + carry = static_cast(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR void multiply(UInt value) { + using half_uint = + conditional_t::value, uint64_t, uint32_t>; + const int shift = num_bits() - bigit_bits; + const UInt lower = static_cast(value); + const UInt upper = value >> num_bits(); + UInt carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + UInt result = lower * bigits_[i] + static_cast(carry); + carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) + + (carry >> bigit_bits); + bigits_[i] = static_cast(result); + } + while (carry != 0) { + bigits_.push_back(static_cast(carry)); + carry >>= bigit_bits; + } + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR void assign(UInt n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = static_cast(n); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + public: + FMT_CONSTEXPR bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + + bigint(const bigint&) = delete; + void operator=(const bigint&) = delete; + + FMT_CONSTEXPR void assign(const bigint& other) { + auto size = other.bigits_.size(); + bigits_.resize(size); + auto data = other.bigits_.data(); + copy(data, data + size, bigits_.data()); + exp_ = other.exp_; + } + + template FMT_CONSTEXPR void operator=(Int n) { + FMT_ASSERT(n > 0, ""); + assign(uint64_or_128_t(n)); + } + + FMT_CONSTEXPR auto num_bigits() const -> int { + return static_cast(bigits_.size()) + exp_; + } + + FMT_CONSTEXPR auto operator<<=(int shift) -> bigint& { + FMT_ASSERT(shift >= 0, ""); + exp_ += shift / bigit_bits; + shift %= bigit_bits; + if (shift == 0) return *this; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + bigit c = bigits_[i] >> (bigit_bits - shift); + bigits_[i] = (bigits_[i] << shift) + carry; + carry = c; + } + if (carry != 0) bigits_.push_back(carry); + return *this; + } + + template FMT_CONSTEXPR auto operator*=(Int value) -> bigint& { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t(value)); + return *this; + } + + friend FMT_CONSTEXPR auto compare(const bigint& b1, const bigint& b2) -> int { + int num_bigits1 = b1.num_bigits(), num_bigits2 = b2.num_bigits(); + if (num_bigits1 != num_bigits2) return num_bigits1 > num_bigits2 ? 1 : -1; + int i = static_cast(b1.bigits_.size()) - 1; + int j = static_cast(b2.bigits_.size()) - 1; + int end = i - j; + if (end < 0) end = 0; + for (; i >= end; --i, --j) { + bigit b1_bigit = b1.bigits_[i], b2_bigit = b2.bigits_[j]; + if (b1_bigit != b2_bigit) return b1_bigit > b2_bigit ? 1 : -1; + } + if (i != j) return i > j ? 1 : -1; + return 0; + } + + // Returns compare(lhs1 + lhs2, rhs). + friend FMT_CONSTEXPR auto add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) -> int { + int max_lhs_bigits = max_of(lhs1.num_bigits(), lhs2.num_bigits()); + int num_rhs_bigits = rhs.num_bigits(); + if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; + if (max_lhs_bigits > num_rhs_bigits) return 1; + double_bigit borrow = 0; + int min_exp = min_of(min_of(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = double_bigit(lhs1.get_bigit(i)) + lhs2.get_bigit(i); + bigit rhs_bigit = rhs.get_bigit(i); + if (sum > rhs_bigit + borrow) return 1; + borrow = rhs_bigit + borrow - sum; + if (borrow > 1) return -1; + borrow <<= bigit_bits; + } + return borrow != 0 ? -1 : 0; + } + + // Assigns pow(10, exp) to this bigint. + FMT_CONSTEXPR20 void assign_pow10(int exp) { + FMT_ASSERT(exp >= 0, ""); + if (exp == 0) return *this = 1; + int bitmask = 1 << (num_bits() - + countl_zero(static_cast(exp)) - 1); + // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by + // repeated squaring and multiplication. + *this = 5; + bitmask >>= 1; + while (bitmask != 0) { + square(); + if ((exp & bitmask) != 0) *this *= 5; + bitmask >>= 1; + } + *this <<= exp; // Multiply by pow(2, exp) by shifting. + } + + FMT_CONSTEXPR20 void square() { + int num_bigits = static_cast(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + basic_memory_buffer n(std::move(bigits_)); + bigits_.resize(to_unsigned(num_result_bigits)); + auto sum = uint128_t(); + for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { + // Compute bigit at position bigit_index of the result by adding + // cross-product terms n[i] * n[j] such that i + j == bigit_index. + for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { + // Most terms are multiplied twice which can be optimized in the future. + sum += double_bigit(n[i]) * n[j]; + } + bigits_[bigit_index] = static_cast(sum); + sum >>= num_bits(); // Compute the carry. + } + // Do the same for the top half. + for (int bigit_index = num_bigits; bigit_index < num_result_bigits; + ++bigit_index) { + for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) + sum += double_bigit(n[i++]) * n[j--]; + bigits_[bigit_index] = static_cast(sum); + sum >>= num_bits(); + } + remove_leading_zeros(); + exp_ *= 2; + } + + // If this bigint has a bigger exponent than other, adds trailing zero to make + // exponents equal. This simplifies some operations such as subtraction. + FMT_CONSTEXPR void align(const bigint& other) { + int exp_difference = exp_ - other.exp_; + if (exp_difference <= 0) return; + int num_bigits = static_cast(bigits_.size()); + bigits_.resize(to_unsigned(num_bigits + exp_difference)); + for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) + bigits_[j] = bigits_[i]; + memset(bigits_.data(), 0, to_unsigned(exp_difference) * sizeof(bigit)); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + FMT_CONSTEXPR auto divmod_assign(const bigint& divisor) -> int { + FMT_ASSERT(this != &divisor, ""); + if (compare(*this, divisor) < 0) return 0; + FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); + align(divisor); + int quotient = 0; + do { + subtract_aligned(divisor); + ++quotient; + } while (compare(*this, divisor) >= 0); + return quotient; + } +}; + +// format_dragon flags. +enum dragon { + predecessor_closer = 1, + fixup = 2, // Run fixup to correct exp10 which can be off by one. + fixed = 4, +}; + +// Formats a floating-point number using a variation of the Fixed-Precision +// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White: +// https://fmt.dev/papers/p372-steele.pdf. +FMT_CONSTEXPR20 inline void format_dragon(basic_fp value, + unsigned flags, int num_digits, + buffer& buf, int& exp10) { + bigint numerator; // 2 * R in (FPP)^2. + bigint denominator; // 2 * S in (FPP)^2. + // lower and upper are differences between value and corresponding boundaries. + bigint lower; // (M^- in (FPP)^2). + bigint upper_store; // upper's value if different from lower. + bigint* upper = nullptr; // (M^+ in (FPP)^2). + // Shift numerator and denominator by an extra bit or two (if lower boundary + // is closer) to make lower and upper integers. This eliminates multiplication + // by 2 during later computations. + bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0; + int shift = is_predecessor_closer ? 2 : 1; + if (value.e >= 0) { + numerator = value.f; + numerator <<= value.e + shift; + lower = 1; + lower <<= value.e; + if (is_predecessor_closer) { + upper_store = 1; + upper_store <<= value.e + 1; + upper = &upper_store; + } + denominator.assign_pow10(exp10); + denominator <<= shift; + } else if (exp10 < 0) { + numerator.assign_pow10(-exp10); + lower.assign(numerator); + if (is_predecessor_closer) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= value.f; + numerator <<= shift; + denominator = 1; + denominator <<= shift - value.e; + } else { + numerator = value.f; + numerator <<= shift; + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower = 1; + if (is_predecessor_closer) { + upper_store = 1ULL << 1; + upper = &upper_store; + } + } + int even = static_cast((value.f & 1) == 0); + if (!upper) upper = &lower; + bool shortest = num_digits < 0; + if ((flags & dragon::fixup) != 0) { + if (add_compare(numerator, *upper, denominator) + even <= 0) { + --exp10; + numerator *= 10; + if (num_digits < 0) { + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1); + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (shortest) { + // Generate the shortest representation. + num_digits = 0; + char* data = buf.data(); + for (;;) { + int digit = numerator.divmod_assign(denominator); + bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. + // numerator + upper >[=] pow10: + bool high = add_compare(numerator, *upper, denominator) + even > 0; + data[num_digits++] = static_cast('0' + digit); + if (low || high) { + if (!low) { + ++data[num_digits - 1]; + } else if (high) { + int result = add_compare(numerator, numerator, denominator); + // Round half to even. + if (result > 0 || (result == 0 && (digit % 2) != 0)) + ++data[num_digits - 1]; + } + buf.try_resize(to_unsigned(num_digits)); + exp10 -= num_digits - 1; + return; + } + numerator *= 10; + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + // Generate the given number of digits. + exp10 -= num_digits - 1; + if (num_digits <= 0) { + auto digit = '0'; + if (num_digits == 0) { + denominator *= 10; + digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; + } + buf.push_back(digit); + return; + } + buf.try_resize(to_unsigned(num_digits)); + for (int i = 0; i < num_digits - 1; ++i) { + int digit = numerator.divmod_assign(denominator); + buf[i] = static_cast('0' + digit); + numerator *= 10; + } + int digit = numerator.divmod_assign(denominator); + auto result = add_compare(numerator, numerator, denominator); + if (result > 0 || (result == 0 && (digit % 2) != 0)) { + if (digit == 9) { + const auto overflow = '0' + 10; + buf[num_digits - 1] = overflow; + // Propagate the carry. + for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] == overflow) { + buf[0] = '1'; + if ((flags & dragon::fixed) != 0) + buf.push_back('0'); + else + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast('0' + digit); +} + +// Formats a floating-point number using the hexfloat format. +template ::value)> +FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, + buffer& buf) { + // float is passed as double to reduce the number of instantiations and to + // simplify implementation. + static_assert(!std::is_same::value, ""); + + using info = dragonbox::float_info; + + // Assume Float is in the format [sign][exponent][significand]. + using carrier_uint = typename info::carrier_uint; + + const auto num_float_significand_bits = detail::num_significand_bits(); + + basic_fp f(value); + f.e += num_float_significand_bits; + if (!has_implicit_bit()) --f.e; + + const auto num_fraction_bits = + num_float_significand_bits + (has_implicit_bit() ? 1 : 0); + const auto num_xdigits = (num_fraction_bits + 3) / 4; + + const auto leading_shift = ((num_xdigits - 1) * 4); + const auto leading_mask = carrier_uint(0xF) << leading_shift; + const auto leading_xdigit = + static_cast((f.f & leading_mask) >> leading_shift); + if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1); + + int print_xdigits = num_xdigits - 1; + if (specs.precision >= 0 && print_xdigits > specs.precision) { + const int shift = ((print_xdigits - specs.precision - 1) * 4); + const auto mask = carrier_uint(0xF) << shift; + const auto v = static_cast((f.f & mask) >> shift); + + if (v >= 8) { + const auto inc = carrier_uint(1) << (shift + 4); + f.f += inc; + f.f &= ~(inc - 1); + } + + // Check long double overflow + if (!has_implicit_bit()) { + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + if ((f.f & implicit_bit) == implicit_bit) { + f.f >>= 4; + f.e += 4; + } + } + + print_xdigits = specs.precision; + } + + char xdigits[num_bits() / 4]; + detail::fill_n(xdigits, sizeof(xdigits), '0'); + format_base2e(4, xdigits, f.f, num_xdigits, specs.upper()); + + // Remove zero tail + while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; + + buf.push_back('0'); + buf.push_back(specs.upper() ? 'X' : 'x'); + buf.push_back(xdigits[0]); + if (specs.alt() || print_xdigits > 0 || print_xdigits < specs.precision) + buf.push_back('.'); + buf.append(xdigits + 1, xdigits + 1 + print_xdigits); + for (; print_xdigits < specs.precision; ++print_xdigits) buf.push_back('0'); + + buf.push_back(specs.upper() ? 'P' : 'p'); + + uint32_t abs_e; + if (f.e < 0) { + buf.push_back('-'); + abs_e = static_cast(-f.e); + } else { + buf.push_back('+'); + abs_e = static_cast(f.e); + } + format_decimal(appender(buf), abs_e, detail::count_digits(abs_e)); +} + +template ::value)> +FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, + buffer& buf) { + format_hexfloat(static_cast(value), specs, buf); +} + +constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t { + // For checking rounding thresholds. + // The kth entry is chosen to be the smallest integer such that the + // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k. + // It is equal to ceil(2^31 + 2^32/10^(k + 1)). + // These are stored in a string literal because we cannot have static arrays + // in constexpr functions and non-static ones are poorly optimized. + return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7" + U"\x800001ae\x8000002b"[index]; +} + +template +FMT_CONSTEXPR20 auto format_float(Float value, int precision, + const format_specs& specs, bool binary32, + buffer& buf) -> int { + // float is passed as double to reduce the number of instantiations. + static_assert(!std::is_same::value, ""); + auto converted_value = convert_float(value); + + const bool fixed = specs.type() == presentation_type::fixed; + if (value == 0) { + if (precision <= 0 || !fixed) { + buf.push_back('0'); + return 0; + } + buf.try_resize(to_unsigned(precision)); + fill_n(buf.data(), precision, '0'); + return -precision; + } + + int exp = 0; + bool use_dragon = true; + unsigned dragon_flags = 0; + if (!is_fast_float() || is_constant_evaluated()) { + const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10) + using info = dragonbox::float_info; + const auto f = basic_fp(converted_value); + // Compute exp, an approximate power of 10, such that + // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1). + // This is based on log10(value) == log2(value) / log2(10) and approximation + // of log2(value) by e + num_fraction_bits idea from double-conversion. + auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10; + exp = static_cast(e); + if (e > exp) ++exp; // Compute ceil. + dragon_flags = dragon::fixup; + } else { + // Extract significand bits and exponent bits. + using info = dragonbox::float_info; + auto br = bit_cast(static_cast(value)); + + const uint64_t significand_mask = + (static_cast(1) << num_significand_bits()) - 1; + uint64_t significand = (br & significand_mask); + int exponent = static_cast((br & exponent_mask()) >> + num_significand_bits()); + + if (exponent != 0) { // Check if normal. + exponent -= exponent_bias() + num_significand_bits(); + significand |= + (static_cast(1) << num_significand_bits()); + significand <<= 1; + } else { + // Normalize subnormal inputs. + FMT_ASSERT(significand != 0, "zeros should not appear here"); + int shift = countl_zero(significand); + FMT_ASSERT(shift >= num_bits() - num_significand_bits(), + ""); + shift -= (num_bits() - num_significand_bits() - 2); + exponent = (std::numeric_limits::min_exponent - + num_significand_bits()) - + shift; + significand <<= shift; + } + + // Compute the first several nonzero decimal significand digits. + // We call the number we get the first segment. + const int k = info::kappa - dragonbox::floor_log10_pow2(exponent); + exp = -k; + const int beta = exponent + dragonbox::floor_log2_pow10(k); + uint64_t first_segment; + bool has_more_segments; + int digits_in_the_first_segment; + { + const auto r = dragonbox::umul192_upper128( + significand << beta, dragonbox::get_cached_power(k)); + first_segment = r.high(); + has_more_segments = r.low() != 0; + + // The first segment can have 18 ~ 19 digits. + if (first_segment >= 1000000000000000000ULL) { + digits_in_the_first_segment = 19; + } else { + // When it is of 18-digits, we align it to 19-digits by adding a bogus + // zero at the end. + digits_in_the_first_segment = 18; + first_segment *= 10; + } + } + + // Compute the actual number of decimal digits to print. + if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment); + + // Use Dragon4 only when there might be not enough digits in the first + // segment. + if (digits_in_the_first_segment > precision) { + use_dragon = false; + + if (precision <= 0) { + exp += digits_in_the_first_segment; + + if (precision < 0) { + // Nothing to do, since all we have are just leading zeros. + buf.try_resize(0); + } else { + // We may need to round-up. + buf.try_resize(1); + if ((first_segment | static_cast(has_more_segments)) > + 5000000000000000000ULL) { + buf[0] = '1'; + } else { + buf[0] = '0'; + } + } + } // precision <= 0 + else { + exp += digits_in_the_first_segment - precision; + + // When precision > 0, we divide the first segment into three + // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits + // in 32-bits which usually allows faster calculation than in + // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize + // division-by-constant for large 64-bit divisors, we do it here + // manually. The magic number 7922816251426433760 below is equal to + // ceil(2^(64+32) / 10^10). + const uint32_t first_subsegment = static_cast( + dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >> + 32); + const uint64_t second_third_subsegments = + first_segment - first_subsegment * 10000000000ULL; + + uint64_t prod; + uint32_t digits; + bool should_round_up; + int number_of_digits_to_print = min_of(precision, 9); + + // Print a 9-digits subsegment, either the first or the second. + auto print_subsegment = [&](uint32_t subsegment, char* buffer) { + int number_of_digits_printed = 0; + + // If we want to print an odd number of digits from the subsegment, + if ((number_of_digits_to_print & 1) != 0) { + // Convert to 64-bit fixed-point fractional form with 1-digit + // integer part. The magic number 720575941 is a good enough + // approximation of 2^(32 + 24) / 10^8; see + // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case + // for details. + prod = ((subsegment * static_cast(720575941)) >> 24) + 1; + digits = static_cast(prod >> 32); + *buffer = static_cast('0' + digits); + number_of_digits_printed++; + } + // If we want to print an even number of digits from the + // first_subsegment, + else { + // Convert to 64-bit fixed-point fractional form with 2-digits + // integer part. The magic number 450359963 is a good enough + // approximation of 2^(32 + 20) / 10^7; see + // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case + // for details. + prod = ((subsegment * static_cast(450359963)) >> 20) + 1; + digits = static_cast(prod >> 32); + write2digits(buffer, digits); + number_of_digits_printed += 2; + } + + // Print all digit pairs. + while (number_of_digits_printed < number_of_digits_to_print) { + prod = static_cast(prod) * static_cast(100); + digits = static_cast(prod >> 32); + write2digits(buffer + number_of_digits_printed, digits); + number_of_digits_printed += 2; + } + }; + + // Print first subsegment. + print_subsegment(first_subsegment, buf.data()); + + // Perform rounding if the first subsegment is the last subsegment to + // print. + if (precision <= 9) { + // Rounding inside the subsegment. + // We round-up if: + // - either the fractional part is strictly larger than 1/2, or + // - the fractional part is exactly 1/2 and the last digit is odd. + // We rely on the following observations: + // - If fractional_part >= threshold, then the fractional part is + // strictly larger than 1/2. + // - If the MSB of fractional_part is set, then the fractional part + // must be at least 1/2. + // - When the MSB of fractional_part is set, either + // second_third_subsegments being nonzero or has_more_segments + // being true means there are further digits not printed, so the + // fractional part is strictly larger than 1/2. + if (precision < 9) { + uint32_t fractional_part = static_cast(prod); + should_round_up = + fractional_part >= fractional_part_rounding_thresholds( + 8 - number_of_digits_to_print) || + ((fractional_part >> 31) & + ((digits & 1) | (second_third_subsegments != 0) | + has_more_segments)) != 0; + } + // Rounding at the subsegment boundary. + // In this case, the fractional part is at least 1/2 if and only if + // second_third_subsegments >= 5000000000ULL, and is strictly larger + // than 1/2 if we further have either second_third_subsegments > + // 5000000000ULL or has_more_segments == true. + else { + should_round_up = second_third_subsegments > 5000000000ULL || + (second_third_subsegments == 5000000000ULL && + ((digits & 1) != 0 || has_more_segments)); + } + } + // Otherwise, print the second subsegment. + else { + // Compilers are not aware of how to leverage the maximum value of + // second_third_subsegments to find out a better magic number which + // allows us to eliminate an additional shift. 1844674407370955162 = + // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))). + const uint32_t second_subsegment = + static_cast(dragonbox::umul128_upper64( + second_third_subsegments, 1844674407370955162ULL)); + const uint32_t third_subsegment = + static_cast(second_third_subsegments) - + second_subsegment * 10; + + number_of_digits_to_print = precision - 9; + print_subsegment(second_subsegment, buf.data() + 9); + + // Rounding inside the subsegment. + if (precision < 18) { + // The condition third_subsegment != 0 implies that the segment was + // of 19 digits, so in this case the third segment should be + // consisting of a genuine digit from the input. + uint32_t fractional_part = static_cast(prod); + should_round_up = + fractional_part >= fractional_part_rounding_thresholds( + 8 - number_of_digits_to_print) || + ((fractional_part >> 31) & + ((digits & 1) | (third_subsegment != 0) | + has_more_segments)) != 0; + } + // Rounding at the subsegment boundary. + else { + // In this case, the segment must be of 19 digits, thus + // the third subsegment should be consisting of a genuine digit from + // the input. + should_round_up = third_subsegment > 5 || + (third_subsegment == 5 && + ((digits & 1) != 0 || has_more_segments)); + } + } + + // Round-up if necessary. + if (should_round_up) { + ++buf[precision - 1]; + for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[precision++] = '0'; + else + ++exp; + } + } + buf.try_resize(to_unsigned(precision)); + } + } // if (digits_in_the_first_segment > precision) + else { + // Adjust the exponent for its use in Dragon4. + exp += digits_in_the_first_segment - 1; + } + } + if (use_dragon) { + auto f = basic_fp(); + bool is_predecessor_closer = binary32 ? f.assign(static_cast(value)) + : f.assign(converted_value); + if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer; + if (fixed) dragon_flags |= dragon::fixed; + // Limit precision to the maximum possible number of significant digits in + // an IEEE754 double because we don't need to generate zeros. + const int max_double_digits = 767; + if (precision > max_double_digits) precision = max_double_digits; + format_dragon(f, dragon_flags, precision, buf, exp); + } + if (!fixed && !specs.alt()) { + // Remove trailing zeros. + auto num_digits = buf.size(); + while (num_digits > 0 && buf[num_digits - 1] == '0') { + --num_digits; + ++exp; + } + buf.try_resize(num_digits); + } + return exp; +} + +// Numbers with exponents greater or equal to the returned value will use +// the exponential notation. +template constexpr auto exp_upper() -> int { + return std::numeric_limits::digits10 != 0 + ? min_of(16, std::numeric_limits::digits10 + 1) + : 16; +} + +template +FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, + locale_ref loc) -> OutputIt { + // Use signbit because value < 0 is false for NaN. + sign s = detail::signbit(value) ? sign::minus : specs.sign(); + + if (!detail::isfinite(value)) + return write_nonfinite(out, detail::isnan(value), specs, s); + + if (specs.align() == align::numeric && s != sign::none) { + *out++ = detail::getsign(s); + s = sign::none; + if (specs.width != 0) --specs.width; + } + + constexpr int exp_upper = detail::exp_upper(); + int precision = specs.precision; + if (precision < 0) { + if (specs.type() != presentation_type::none) { + precision = 6; + } else if (is_fast_float::value && !is_constant_evaluated()) { + // Use Dragonbox for the shortest format. + using floaty = conditional_t= sizeof(double), double, float>; + auto dec = dragonbox::to_decimal(static_cast(value)); + return write_float(out, dec, specs, s, exp_upper, loc); + } + } + + memory_buffer buffer; + if (specs.type() == presentation_type::hexfloat) { + if (s != sign::none) buffer.push_back(detail::getsign(s)); + format_hexfloat(convert_float(value), specs, buffer); + return write_bytes(out, {buffer.data(), buffer.size()}, + specs); + } + + if (specs.type() == presentation_type::exp) { + if (precision == max_value()) + report_error("number is too big"); + else + ++precision; + if (specs.precision != 0) specs.set_alt(); + } else if (specs.type() == presentation_type::fixed) { + if (specs.precision != 0) specs.set_alt(); + } else if (precision == 0) { + precision = 1; + } + int exp = format_float(convert_float(value), precision, specs, + std::is_same(), buffer); + + specs.precision = precision; + auto f = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; + return write_float(out, f, specs, s, exp_upper, loc); +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs, + locale_ref loc = {}) -> OutputIt { + return specs.localized() && write_loc(out, value, specs, loc) + ? out + : write_float(out, value, specs, loc); +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { + if (is_constant_evaluated()) return write(out, value, format_specs()); + + auto s = detail::signbit(value) ? sign::minus : sign::none; + + constexpr auto specs = format_specs(); + using floaty = conditional_t= sizeof(double), double, float>; + using floaty_uint = typename dragonbox::float_info::carrier_uint; + floaty_uint mask = exponent_mask(); + if ((bit_cast(value) & mask) == mask) + return write_nonfinite(out, std::isnan(value), specs, s); + + auto dec = dragonbox::to_decimal(static_cast(value)); + return write_float(out, dec, specs, s, exp_upper(), {}); +} + +template ::value && + !is_fast_float::value)> +inline auto write(OutputIt out, T value) -> OutputIt { + return write(out, value, format_specs()); +} + +template +auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) + -> OutputIt { + FMT_ASSERT(false, ""); + return out; +} + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view value) + -> OutputIt { + return copy_noinline(value.begin(), value.end(), out); +} + +template ::value)> +constexpr auto write(OutputIt out, const T& value) -> OutputIt { + return write(out, to_string_view(value)); +} + +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. +template < + typename Char, typename OutputIt, typename T, + bool check = std::is_enum::value && !std::is_same::value && + mapped_type_constant::value != type::custom_type, + FMT_ENABLE_IF(check)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + return write(out, static_cast>(value)); +} + +template ::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value, const format_specs& specs = {}, + locale_ref = {}) -> OutputIt { + return specs.type() != presentation_type::none && + specs.type() != presentation_type::string + ? write(out, value ? 1 : 0, specs, {}) + : write_bytes(out, value ? "true" : "false", specs); +} + +template +FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template +FMT_CONSTEXPR20 auto write(OutputIt out, const Char* value) -> OutputIt { + if (value) return write(out, basic_string_view(value)); + report_error("string pointer is null"); + return out; +} + +template ::value)> +auto write(OutputIt out, const T* value, const format_specs& specs = {}, + locale_ref = {}) -> OutputIt { + return write_ptr(out, bit_cast(value), &specs); +} + +template ::value == + type::custom_type && + !std::is_fundamental::value)> +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> OutputIt { + auto f = formatter(); + auto parse_ctx = parse_context({}); + f.parse(parse_ctx); + auto ctx = basic_format_context(out, {}, {}); + return f.format(value, ctx); +} + +template +using is_builtin = + bool_constant::value || FMT_BUILTIN_TYPES>; + +// An argument visitor that formats the argument and writes it via the output +// iterator. It's a class and not a generic lambda for compatibility with C++11. +template struct default_arg_formatter { + using context = buffered_context; + + basic_appender out; + + void operator()(monostate) { report_error("argument not found"); } + + template ::value)> + void operator()(T value) { + write(out, value); + } + + template ::value)> + void operator()(T) { + FMT_ASSERT(false, ""); + } + + void operator()(typename basic_format_arg::handle h) { + // Use a null locale since the default format must be unlocalized. + auto parse_ctx = parse_context({}); + auto format_ctx = context(out, {}, {}); + h.format(parse_ctx, format_ctx); + } +}; + +template struct arg_formatter { + basic_appender out; + const format_specs& specs; + FMT_NO_UNIQUE_ADDRESS locale_ref locale; + + template ::value)> + FMT_CONSTEXPR FMT_INLINE void operator()(T value) { + detail::write(out, value, specs, locale); + } + + template ::value)> + void operator()(T) { + FMT_ASSERT(false, ""); + } + + void operator()(typename basic_format_arg>::handle) { + // User-defined types are handled separately because they require access + // to the parse context. + } +}; + +struct dynamic_spec_getter { + template ::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + return is_negative(value) ? ~0ull : static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + report_error("width/precision is not integer"); + return 0; + } +}; + +template +FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> basic_format_arg { + auto arg = ctx.arg(id); + if (!arg) report_error("argument not found"); + return arg; +} + +template +FMT_CONSTEXPR int get_dynamic_spec( + arg_id_kind kind, const arg_ref& ref, + Context& ctx) { + FMT_ASSERT(kind != arg_id_kind::none, ""); + auto arg = + kind == arg_id_kind::index ? ctx.arg(ref.index) : ctx.arg(ref.name); + if (!arg) report_error("argument not found"); + unsigned long long value = arg.visit(dynamic_spec_getter()); + if (value > to_unsigned(max_value())) + report_error("width/precision is out of range"); + return static_cast(value); +} + +template +FMT_CONSTEXPR void handle_dynamic_spec( + arg_id_kind kind, int& value, + const arg_ref& ref, Context& ctx) { + if (kind != arg_id_kind::none) value = get_dynamic_spec(kind, ref, ctx); +} + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template Str> +struct static_named_arg : view { + static constexpr auto name = Str.data; + + const T& value; + static_named_arg(const T& v) : value(v) {} +}; + +template Str> +struct is_named_arg> : std::true_type {}; + +template Str> +struct is_static_named_arg> : std::true_type { +}; + +template Str> +struct udl_arg { + template auto operator=(T&& value) const { + return static_named_arg(std::forward(value)); + } +}; +#else +template struct udl_arg { + const Char* str; + + template auto operator=(T&& value) const -> named_arg { + return {str, std::forward(value)}; + } +}; +#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS + +template struct format_handler { + parse_context parse_ctx; + buffered_context ctx; + + void on_text(const Char* begin, const Char* end) { + copy_noinline(begin, end, ctx.out()); + } + + FMT_CONSTEXPR auto on_arg_id() -> int { return parse_ctx.next_arg_id(); } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + parse_ctx.check_arg_id(id); + return id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view id) -> int { + parse_ctx.check_arg_id(id); + int arg_id = ctx.arg_id(id); + if (arg_id < 0) report_error("argument not found"); + return arg_id; + } + + FMT_INLINE void on_replacement_field(int id, const Char*) { + ctx.arg(id).visit(default_arg_formatter{ctx.out()}); + } + + auto on_format_specs(int id, const Char* begin, const Char* end) + -> const Char* { + auto arg = get_arg(ctx, id); + // Not using a visitor for custom types gives better codegen. + if (arg.format_custom(begin, parse_ctx, ctx)) return parse_ctx.begin(); + + auto specs = dynamic_format_specs(); + begin = parse_format_specs(begin, end, specs, parse_ctx, arg.type()); + if (specs.dynamic()) { + handle_dynamic_spec(specs.dynamic_width(), specs.width, specs.width_ref, + ctx); + handle_dynamic_spec(specs.dynamic_precision(), specs.precision, + specs.precision_ref, ctx); + } + + arg.visit(arg_formatter{ctx.out(), specs, ctx.locale()}); + return begin; + } + + FMT_NORETURN void on_error(const char* message) { report_error(message); } +}; + +using format_func = void (*)(detail::buffer&, int, const char*); +FMT_API void do_report_error(format_func func, int error_code, + const char* message) noexcept; + +FMT_API void format_error_code(buffer& out, int error_code, + string_view message) noexcept; + +template +template +FMT_CONSTEXPR auto native_formatter::format( + const T& val, FormatContext& ctx) const -> decltype(ctx.out()) { + if (!specs_.dynamic()) + return write(ctx.out(), val, specs_, ctx.locale()); + auto specs = format_specs(specs_); + handle_dynamic_spec(specs.dynamic_width(), specs.width, specs_.width_ref, + ctx); + handle_dynamic_spec(specs.dynamic_precision(), specs.precision, + specs_.precision_ref, ctx); + return write(ctx.out(), val, specs, ctx.locale()); +} + +// DEPRECATED! https://github.com/fmtlib/fmt/issues/4292. +template +struct is_locale : std::false_type {}; +template +struct is_locale> : std::true_type {}; + +// DEPRECATED! +template struct vformat_args { + using type = basic_format_args>; +}; +template <> struct vformat_args { + using type = format_args; +}; + +template +void vformat_to(buffer& buf, basic_string_view fmt, + typename vformat_args::type args, locale_ref loc = {}) { + auto out = basic_appender(buf); + parse_format_string( + fmt, format_handler{parse_context(fmt), {out, args, loc}}); +} +} // namespace detail + +FMT_BEGIN_EXPORT + +// A generic formatting context with custom output iterator and character +// (code unit) support. Char is the format string code unit type which can be +// different from OutputIt::value_type. +template class generic_context { + private: + OutputIt out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + using char_type = Char; + using iterator = OutputIt; + using parse_context_type FMT_DEPRECATED = parse_context; + template + using formatter_type FMT_DEPRECATED = formatter; + enum { builtin_types = FMT_BUILTIN_TYPES }; + + constexpr generic_context(OutputIt out, + basic_format_args args, + detail::locale_ref loc = {}) + : out_(out), args_(args), loc_(loc) {} + generic_context(generic_context&&) = default; + generic_context(const generic_context&) = delete; + void operator=(const generic_context&) = delete; + + constexpr auto arg(int id) const -> basic_format_arg { + return args_.get(id); + } + auto arg(basic_string_view name) const + -> basic_format_arg { + return args_.get(name); + } + constexpr auto arg_id(basic_string_view name) const -> int { + return args_.get_id(name); + } + + constexpr auto out() const -> iterator { return out_; } + + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator()) out_ = it; + } + + constexpr auto locale() const -> detail::locale_ref { return loc_; } +}; + +class loc_value { + private: + basic_format_arg value_; + + public: + template ::value)> + loc_value(T value) : value_(value) {} + + template ::value)> + loc_value(T) {} + + template auto visit(Visitor&& vis) -> decltype(vis(0)) { + return value_.visit(vis); + } +}; + +// A locale facet that formats values in UTF-8. +// It is parameterized on the locale to avoid the heavy include. +template class format_facet : public Locale::facet { + private: + std::string separator_; + std::string grouping_; + std::string decimal_point_; + + protected: + virtual auto do_put(appender out, loc_value val, + const format_specs& specs) const -> bool; + + public: + static FMT_API typename Locale::id id; + + explicit format_facet(Locale& loc); + explicit format_facet(string_view sep = "", std::string grouping = "\3", + std::string decimal_point = ".") + : separator_(sep.data(), sep.size()), + grouping_(grouping), + decimal_point_(decimal_point) {} + + auto put(appender out, loc_value val, const format_specs& specs) const + -> bool { + return do_put(out, val, specs); + } +}; + +#define FMT_FORMAT_AS(Type, Base) \ + template \ + struct formatter : formatter { \ + template \ + FMT_CONSTEXPR auto format(Type value, FormatContext& ctx) const \ + -> decltype(ctx.out()) { \ + return formatter::format(value, ctx); \ + } \ + } + +FMT_FORMAT_AS(signed char, int); +FMT_FORMAT_AS(unsigned char, unsigned); +FMT_FORMAT_AS(short, int); +FMT_FORMAT_AS(unsigned short, unsigned); +FMT_FORMAT_AS(long, detail::long_type); +FMT_FORMAT_AS(unsigned long, detail::ulong_type); +FMT_FORMAT_AS(Char*, const Char*); +FMT_FORMAT_AS(detail::std_string_view, basic_string_view); +FMT_FORMAT_AS(std::nullptr_t, const void*); +FMT_FORMAT_AS(void*, const void*); + +template +struct formatter : formatter, Char> {}; + +template +class formatter, Char> + : public formatter, Char> {}; + +template +struct formatter, Char> : formatter {}; +template +struct formatter, Char> + : formatter {}; + +template +struct formatter + : detail::native_formatter {}; + +template +struct formatter>> + : formatter, Char> { + template + FMT_CONSTEXPR auto format(const T& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto&& val = format_as(value); // Make an lvalue reference for format. + return formatter, Char>::format(val, ctx); + } +}; + +/** + * Converts `p` to `const void*` for pointer formatting. + * + * **Example**: + * + * auto s = fmt::format("{}", fmt::ptr(p)); + */ +template auto ptr(T p) -> const void* { + static_assert(std::is_pointer::value, ""); + return detail::bit_cast(p); +} + +/** + * Converts `e` to the underlying type. + * + * **Example**: + * + * enum class color { red, green, blue }; + * auto s = fmt::format("{}", fmt::underlying(color::red)); // s == "0" + */ +template +constexpr auto underlying(Enum e) noexcept -> underlying_t { + return static_cast>(e); +} + +namespace enums { +template ::value)> +constexpr auto format_as(Enum e) noexcept -> underlying_t { + return static_cast>(e); +} +} // namespace enums + +#ifdef __cpp_lib_byte +template <> struct formatter : formatter { + static auto format_as(std::byte b) -> unsigned char { + return static_cast(b); + } + template + auto format(std::byte b, Context& ctx) const -> decltype(ctx.out()) { + return formatter::format(format_as(b), ctx); + } +}; +#endif + +struct bytes { + string_view data; + + inline explicit bytes(string_view s) : data(s) {} +}; + +template <> struct formatter { + private: + detail::dynamic_format_specs<> specs_; + + public: + FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* { + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type::string_type); + } + + template + auto format(bytes b, FormatContext& ctx) const -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision, + specs.precision_ref, ctx); + return detail::write_bytes(ctx.out(), b.data, specs); + } +}; + +// group_digits_view is not derived from view because it copies the argument. +template struct group_digits_view { + T value; +}; + +/** + * Returns a view that formats an integer value using ',' as a + * locale-independent thousands separator. + * + * **Example**: + * + * fmt::print("{}", fmt::group_digits(12345)); + * // Output: "12,345" + */ +template auto group_digits(T value) -> group_digits_view { + return {value}; +} + +template struct formatter> : formatter { + private: + detail::dynamic_format_specs<> specs_; + + public: + FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* { + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type::int_type); + } + + template + auto format(group_digits_view view, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision, + specs.precision_ref, ctx); + auto arg = detail::make_write_int_arg(view.value, specs.sign()); + return detail::write_int( + ctx.out(), static_cast>(arg.abs_value), + arg.prefix, specs, detail::digit_grouping("\3", ",")); + } +}; + +template struct nested_view { + const formatter* fmt; + const T* value; +}; + +template +struct formatter, Char> { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return ctx.begin(); + } + template + auto format(nested_view view, FormatContext& ctx) const + -> decltype(ctx.out()) { + return view.fmt->format(*view.value, ctx); + } +}; + +template struct nested_formatter { + private: + basic_specs specs_; + int width_; + formatter formatter_; + + public: + constexpr nested_formatter() : width_(0) {} + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(), end = ctx.end(); + if (it == end) return it; + auto specs = format_specs(); + it = detail::parse_align(it, end, specs); + specs_ = specs; + Char c = *it; + auto width_ref = detail::arg_ref(); + if ((c >= '0' && c <= '9') || c == '{') { + it = detail::parse_width(it, end, specs, width_ref, ctx); + width_ = specs.width; + } + ctx.advance_to(it); + return formatter_.parse(ctx); + } + + template + auto write_padded(FormatContext& ctx, F write) const -> decltype(ctx.out()) { + if (width_ == 0) return write(ctx.out()); + auto buf = basic_memory_buffer(); + write(basic_appender(buf)); + auto specs = format_specs(); + specs.width = width_; + specs.copy_fill_from(specs_); + specs.set_align(specs_.align()); + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } + + auto nested(const T& value) const -> nested_view { + return nested_view{&formatter_, &value}; + } +}; + +inline namespace literals { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template constexpr auto operator""_a() { + using char_t = remove_cvref_t; + return detail::udl_arg(); +} +#else +/** + * User-defined literal equivalent of `fmt::arg`. + * + * **Example**: + * + * using namespace fmt::literals; + * fmt::print("The answer is {answer}.", "answer"_a=42); + */ +constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg { + return {s}; +} +#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS +} // namespace literals + +/// A fast integer formatter. +class format_int { + private: + // Buffer should be large enough to hold all digits (digits10 + 1), + // a sign and a null character. + enum { buffer_size = std::numeric_limits::digits10 + 3 }; + mutable char buffer_[buffer_size]; + char* str_; + + template + FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* { + auto n = static_cast>(value); + return detail::do_format_decimal(buffer_, n, buffer_size - 1); + } + + template + FMT_CONSTEXPR20 auto format_signed(Int value) -> char* { + auto abs_value = static_cast>(value); + bool negative = value < 0; + if (negative) abs_value = 0 - abs_value; + auto begin = format_unsigned(abs_value); + if (negative) *--begin = '-'; + return begin; + } + + public: + FMT_CONSTEXPR20 explicit format_int(int value) : str_(format_signed(value)) {} + FMT_CONSTEXPR20 explicit format_int(long value) + : str_(format_signed(value)) {} + FMT_CONSTEXPR20 explicit format_int(long long value) + : str_(format_signed(value)) {} + FMT_CONSTEXPR20 explicit format_int(unsigned value) + : str_(format_unsigned(value)) {} + FMT_CONSTEXPR20 explicit format_int(unsigned long value) + : str_(format_unsigned(value)) {} + FMT_CONSTEXPR20 explicit format_int(unsigned long long value) + : str_(format_unsigned(value)) {} + + /// Returns the number of characters written to the output buffer. + FMT_CONSTEXPR20 auto size() const -> size_t { + return detail::to_unsigned(buffer_ - str_ + buffer_size - 1); + } + + /// Returns a pointer to the output buffer content. No terminating null + /// character is appended. + FMT_CONSTEXPR20 auto data() const -> const char* { return str_; } + + /// Returns a pointer to the output buffer content with terminating null + /// character appended. + FMT_CONSTEXPR20 auto c_str() const -> const char* { + buffer_[buffer_size - 1] = '\0'; + return str_; + } + + /// Returns the content of the output buffer as an `std::string`. + inline auto str() const -> std::string { return {str_, size()}; } +}; + +#define FMT_STRING_IMPL(s, base) \ + [] { \ + /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ + /* Use a macro-like name to avoid shadowing warnings. */ \ + struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \ + using char_type = fmt::remove_cvref_t; \ + constexpr explicit operator fmt::basic_string_view() const { \ + return fmt::detail::compile_string_to_view(s); \ + } \ + }; \ + using FMT_STRING_VIEW = \ + fmt::basic_string_view; \ + fmt::detail::ignore_unused(FMT_STRING_VIEW(FMT_COMPILE_STRING())); \ + return FMT_COMPILE_STRING(); \ + }() + +/** + * Constructs a legacy compile-time format string from a string literal `s`. + * + * **Example**: + * + * // A compile-time error because 'd' is an invalid specifier for strings. + * std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); + */ +#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string) + +FMT_API auto vsystem_error(int error_code, string_view fmt, format_args args) + -> std::system_error; + +/** + * Constructs `std::system_error` with a message formatted with + * `fmt::format(fmt, args...)`. + * `error_code` is a system error code as given by `errno`. + * + * **Example**: + * + * // This throws std::system_error with the description + * // cannot open file 'madeup': No such file or directory + * // or similar (system message may vary). + * const char* filename = "madeup"; + * FILE* file = fopen(filename, "r"); + * if (!file) + * throw fmt::system_error(errno, "cannot open file '{}'", filename); + */ +template +auto system_error(int error_code, format_string fmt, T&&... args) + -> std::system_error { + return vsystem_error(error_code, fmt.str, vargs{{args...}}); +} + +/** + * Formats an error message for an error returned by an operating system or a + * language runtime, for example a file opening error, and writes it to `out`. + * The format is the same as the one used by `std::system_error(ec, message)` + * where `ec` is `std::error_code(error_code, std::generic_category())`. + * It is implementation-defined but normally looks like: + * + * : + * + * where `` is the passed message and `` is the system + * message corresponding to the error code. + * `error_code` is a system error code as given by `errno`. + */ +FMT_API void format_system_error(detail::buffer& out, int error_code, + const char* message) noexcept; + +// Reports a system error without throwing an exception. +// Can be used to report errors from destructors. +FMT_API void report_system_error(int error_code, const char* message) noexcept; + +template ::value)> +inline auto vformat(const Locale& loc, string_view fmt, format_args args) + -> std::string { + auto buf = memory_buffer(); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return {buf.data(), buf.size()}; +} + +template ::value)> +FMT_INLINE auto format(const Locale& loc, format_string fmt, T&&... args) + -> std::string { + return vformat(loc, fmt.str, vargs{{args...}}); +} + +template ::value)> +auto vformat_to(OutputIt out, const Locale& loc, string_view fmt, + format_args args) -> OutputIt { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return detail::get_iterator(buf, out); +} + +template ::value&& + detail::is_locale::value)> +FMT_INLINE auto format_to(OutputIt out, const Locale& loc, + format_string fmt, T&&... args) -> OutputIt { + return fmt::vformat_to(out, loc, fmt.str, vargs{{args...}}); +} + +template ::value)> +FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc, + format_string fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, fmt.str, vargs{{args...}}, + detail::locale_ref(loc)); + return buf.count(); +} + +FMT_API auto vformat(string_view fmt, format_args args) -> std::string; + +/** + * Formats `args` according to specifications in `fmt` and returns the result + * as a string. + * + * **Example**: + * + * #include + * std::string message = fmt::format("The answer is {}.", 42); + */ +template +FMT_NODISCARD FMT_INLINE auto format(format_string fmt, T&&... args) + -> std::string { + return vformat(fmt.str, vargs{{args...}}); +} + +/** + * Converts `value` to `std::string` using the default format for type `T`. + * + * **Example**: + * + * std::string answer = fmt::to_string(42); + */ +template ::value)> +FMT_NODISCARD auto to_string(T value) -> std::string { + // The buffer should be large enough to store the number including the sign + // or "false" for bool. + char buffer[max_of(detail::digits10() + 2, 5)]; + return {buffer, detail::write(buffer, value)}; +} + +template ::value)> +FMT_NODISCARD auto to_string(const T& value) -> std::string { + return to_string(format_as(value)); +} + +template ::value && + !detail::use_format_as::value)> +FMT_NODISCARD auto to_string(const T& value) -> std::string { + auto buffer = memory_buffer(); + detail::write(appender(buffer), value); + return {buffer.data(), buffer.size()}; +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline +# include "format-inl.h" +#endif + +// Restore _LIBCPP_REMOVE_TRANSITIVE_INCLUDES. +#ifdef FMT_REMOVE_TRANSITIVE_INCLUDES +# undef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +#endif + +#endif // FMT_FORMAT_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/os.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/os.h new file mode 100755 index 0000000000000000000000000000000000000000..ca7555d1b07a3c947ffa0886b6beb77bbfd311da --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/os.h @@ -0,0 +1,427 @@ +// Formatting library for C++ - optional OS-specific functionality +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_OS_H_ +#define FMT_OS_H_ + +#include "format.h" + +#ifndef FMT_MODULE +# include +# include +# include +# include // std::system_error + +# if FMT_HAS_INCLUDE() +# include // LC_NUMERIC_MASK on macOS +# endif +#endif // FMT_MODULE + +#ifndef FMT_USE_FCNTL +// UWP doesn't provide _pipe. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include +# endif +# if (FMT_HAS_INCLUDE() || defined(__APPLE__) || \ + defined(__linux__)) && \ + (!defined(WINAPI_FAMILY) || \ + (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# include // for O_RDONLY +# define FMT_USE_FCNTL 1 +# else +# define FMT_USE_FCNTL 0 +# endif +#endif + +#ifndef FMT_POSIX +# if defined(_WIN32) && !defined(__MINGW32__) +// Fix warnings about deprecated symbols. +# define FMT_POSIX(call) _##call +# else +# define FMT_POSIX(call) call +# endif +#endif + +// Calls to system functions are wrapped in FMT_SYSTEM for testability. +#ifdef FMT_SYSTEM +# define FMT_HAS_SYSTEM +# define FMT_POSIX_CALL(call) FMT_SYSTEM(call) +#else +# define FMT_SYSTEM(call) ::call +# ifdef _WIN32 +// Fix warnings about deprecated symbols. +# define FMT_POSIX_CALL(call) ::_##call +# else +# define FMT_POSIX_CALL(call) ::call +# endif +#endif + +// Retries the expression while it evaluates to error_result and errno +// equals to EINTR. +#ifndef _WIN32 +# define FMT_RETRY_VAL(result, expression, error_result) \ + do { \ + (result) = (expression); \ + } while ((result) == (error_result) && errno == EINTR) +#else +# define FMT_RETRY_VAL(result, expression, error_result) result = (expression) +#endif + +#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +/** + * A reference to a null-terminated string. It can be constructed from a C + * string or `std::string`. + * + * You can use one of the following type aliases for common character types: + * + * +---------------+-----------------------------+ + * | Type | Definition | + * +===============+=============================+ + * | cstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * | wcstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * + * This class is most useful as a parameter type for functions that wrap C APIs. + */ +template class basic_cstring_view { + private: + const Char* data_; + + public: + /// Constructs a string reference object from a C string. + basic_cstring_view(const Char* s) : data_(s) {} + + /// Constructs a string reference from an `std::string` object. + basic_cstring_view(const std::basic_string& s) : data_(s.c_str()) {} + + /// Returns the pointer to a C string. + auto c_str() const -> const Char* { return data_; } +}; + +using cstring_view = basic_cstring_view; +using wcstring_view = basic_cstring_view; + +#ifdef _WIN32 +FMT_API const std::error_category& system_category() noexcept; + +namespace detail { +FMT_API void format_windows_error(buffer& out, int error_code, + const char* message) noexcept; +} + +FMT_API std::system_error vwindows_error(int error_code, string_view fmt, + format_args args); + +/** + * Constructs a `std::system_error` object with the description of the form + * + * : + * + * where `` is the formatted message and `` is the + * system message corresponding to the error code. + * `error_code` is a Windows error code as given by `GetLastError`. + * If `error_code` is not a valid error code such as -1, the system message + * will look like "error -1". + * + * **Example**: + * + * // This throws a system_error with the description + * // cannot open file 'madeup': The system cannot find the file + * specified. + * // or similar (system message may vary). + * const char *filename = "madeup"; + * LPOFSTRUCT of = LPOFSTRUCT(); + * HFILE file = OpenFile(filename, &of, OF_READ); + * if (file == HFILE_ERROR) { + * throw fmt::windows_error(GetLastError(), + * "cannot open file '{}'", filename); + * } + */ +template +auto windows_error(int error_code, string_view message, const T&... args) + -> std::system_error { + return vwindows_error(error_code, message, vargs{{args...}}); +} + +// Reports a Windows error without throwing an exception. +// Can be used to report errors from destructors. +FMT_API void report_windows_error(int error_code, const char* message) noexcept; +#else +inline auto system_category() noexcept -> const std::error_category& { + return std::system_category(); +} +#endif // _WIN32 + +// std::system is not available on some platforms such as iOS (#2248). +#ifdef __OSX__ +template > +void say(const S& fmt, Args&&... args) { + std::system(format("say \"{}\"", format(fmt, args...)).c_str()); +} +#endif + +// A buffered file. +class buffered_file { + private: + FILE* file_; + + friend class file; + + inline explicit buffered_file(FILE* f) : file_(f) {} + + public: + buffered_file(const buffered_file&) = delete; + void operator=(const buffered_file&) = delete; + + // Constructs a buffered_file object which doesn't represent any file. + inline buffered_file() noexcept : file_(nullptr) {} + + // Destroys the object closing the file it represents if any. + FMT_API ~buffered_file() noexcept; + + public: + inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) { + other.file_ = nullptr; + } + + inline auto operator=(buffered_file&& other) -> buffered_file& { + close(); + file_ = other.file_; + other.file_ = nullptr; + return *this; + } + + // Opens a file. + FMT_API buffered_file(cstring_view filename, cstring_view mode); + + // Closes the file. + FMT_API void close(); + + // Returns the pointer to a FILE object representing this file. + inline auto get() const noexcept -> FILE* { return file_; } + + FMT_API auto descriptor() const -> int; + + template + inline void print(string_view fmt, const T&... args) { + fmt::vargs vargs = {{args...}}; + detail::is_locking() ? fmt::vprint_buffered(file_, fmt, vargs) + : fmt::vprint(file_, fmt, vargs); + } +}; + +#if FMT_USE_FCNTL + +// A file. Closed file is represented by a file object with descriptor -1. +// Methods that are not declared with noexcept may throw +// fmt::system_error in case of failure. Note that some errors such as +// closing the file multiple times will cause a crash on Windows rather +// than an exception. You can get standard behavior by overriding the +// invalid parameter handler with _set_invalid_parameter_handler. +class FMT_API file { + private: + int fd_; // File descriptor. + + // Constructs a file object with a given descriptor. + explicit file(int fd) : fd_(fd) {} + + friend struct pipe; + + public: + // Possible values for the oflag argument to the export_class. + enum { + RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only. + WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only. + RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing. + CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist. + APPEND = FMT_POSIX(O_APPEND), // Open in append mode. + TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file. + }; + + // Constructs a file object which doesn't represent any file. + inline file() noexcept : fd_(-1) {} + + // Opens a file and constructs a file object representing this file. + file(cstring_view path, int oflag); + + public: + file(const file&) = delete; + void operator=(const file&) = delete; + + inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; } + + // Move assignment is not noexcept because close may throw. + inline auto operator=(file&& other) -> file& { + close(); + fd_ = other.fd_; + other.fd_ = -1; + return *this; + } + + // Destroys the object closing the file it represents if any. + ~file() noexcept; + + // Returns the file descriptor. + inline auto descriptor() const noexcept -> int { return fd_; } + + // Closes the file. + void close(); + + // Returns the file size. The size has signed type for consistency with + // stat::st_size. + auto size() const -> long long; + + // Attempts to read count bytes from the file into the specified buffer. + auto read(void* buffer, size_t count) -> size_t; + + // Attempts to write count bytes from the specified buffer to the file. + auto write(const void* buffer, size_t count) -> size_t; + + // Duplicates a file descriptor with the dup function and returns + // the duplicate as a file object. + static auto dup(int fd) -> file; + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd, std::error_code& ec) noexcept; + + // Creates a buffered_file object associated with this file and detaches + // this file object from the file. + auto fdopen(const char* mode) -> buffered_file; + +# if defined(_WIN32) && !defined(__MINGW32__) + // Opens a file and constructs a file object representing this file by + // wcstring_view filename. Windows only. + static file open_windows_file(wcstring_view path, int oflag); +# endif +}; + +struct FMT_API pipe { + file read_end; + file write_end; + + // Creates a pipe setting up read_end and write_end file objects for reading + // and writing respectively. + pipe(); +}; + +// Returns the memory page size. +auto getpagesize() -> long; + +namespace detail { + +struct buffer_size { + constexpr buffer_size() = default; + size_t value = 0; + FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size { + auto bs = buffer_size(); + bs.value = val; + return bs; + } +}; + +struct ostream_params { + int oflag = file::WRONLY | file::CREATE | file::TRUNC; + size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768; + + constexpr ostream_params() {} + + template + ostream_params(T... params, int new_oflag) : ostream_params(params...) { + oflag = new_oflag; + } + + template + ostream_params(T... params, detail::buffer_size bs) + : ostream_params(params...) { + this->buffer_size = bs.value; + } + +// Intel has a bug that results in failure to deduce a export_class +// for empty parameter packs. +# if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000 + ostream_params(int new_oflag) : oflag(new_oflag) {} + ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {} +# endif +}; + +} // namespace detail + +FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size(); + +/// A fast buffered output stream for writing from a single thread. Writing from +/// multiple threads without external synchronization may result in a data race. +class FMT_API ostream : private detail::buffer { + private: + file file_; + + ostream(cstring_view path, const detail::ostream_params& params); + + static void grow(buffer& buf, size_t); + + public: + ostream(ostream&& other) noexcept; + ~ostream(); + + operator writer() { + detail::buffer& buf = *this; + return buf; + } + + inline void flush() { + if (size() == 0) return; + file_.write(data(), size() * sizeof(data()[0])); + clear(); + } + + template + friend auto output_file(cstring_view path, T... params) -> ostream; + + inline void close() { + flush(); + file_.close(); + } + + /// Formats `args` according to specifications in `fmt` and writes the + /// output to the file. + template void print(format_string fmt, T&&... args) { + vformat_to(appender(*this), fmt.str, vargs{{args...}}); + } +}; + +/** + * Opens a file for writing. Supported parameters passed in `params`: + * + * - ``: Flags passed to [open]( + * https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html) + * (`file::WRONLY | file::CREATE | file::TRUNC` by default) + * - `buffer_size=`: Output buffer size + * + * **Example**: + * + * auto out = fmt::output_file("guide.txt"); + * out.print("Don't {}", "Panic"); + */ +template +inline auto output_file(cstring_view path, T... params) -> ostream { + return {path, detail::ostream_params(params...)}; +} +#endif // FMT_USE_FCNTL + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_OS_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/ostream.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/ostream.h new file mode 100755 index 0000000000000000000000000000000000000000..7bec4efe2b318cb3e6429ea2e3cc11f4bf8b4fb0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/ostream.h @@ -0,0 +1,167 @@ +// Formatting library for C++ - std::ostream support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +#ifndef FMT_MODULE +# include // std::filebuf +#endif + +#ifdef _WIN32 +# ifdef __GLIBCXX__ +# include +# include +# endif +# include +#endif + +#include "chrono.h" // formatbuf + +#ifdef _MSVC_STL_UPDATE +# define FMT_MSVC_STL_UPDATE _MSVC_STL_UPDATE +#elif defined(_MSC_VER) && _MSC_VER < 1912 // VS 15.5 +# define FMT_MSVC_STL_UPDATE _MSVC_LANG +#else +# define FMT_MSVC_STL_UPDATE 0 +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +// Generate a unique explicit instantion in every translation unit using a tag +// type in an anonymous namespace. +namespace { +struct file_access_tag {}; +} // namespace +template +class file_access { + friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; } +}; + +#if FMT_MSVC_STL_UPDATE +template class file_access; +auto get_file(std::filebuf&) -> FILE*; +#endif + +// Write the content of buf to os. +// It is a separate function rather than a part of vprint to simplify testing. +template +void write_buffer(std::basic_ostream& os, buffer& buf) { + const Char* buf_data = buf.data(); + using unsigned_streamsize = make_unsigned_t; + unsigned_streamsize size = buf.size(); + unsigned_streamsize max_size = to_unsigned(max_value()); + do { + unsigned_streamsize n = size <= max_size ? size : max_size; + os.write(buf_data, static_cast(n)); + buf_data += n; + size -= n; + } while (size != 0); +} + +template struct streamed_view { + const T& value; +}; +} // namespace detail + +// Formats an object of type T that has an overloaded ostream operator<<. +template +struct basic_ostream_formatter : formatter, Char> { + void set_debug_format() = delete; + + template + auto format(const T& value, Context& ctx) const -> decltype(ctx.out()) { + auto buffer = basic_memory_buffer(); + auto&& formatbuf = detail::formatbuf>(buffer); + auto&& output = std::basic_ostream(&formatbuf); + output.imbue(std::locale::classic()); // The default is always unlocalized. + output << value; + output.exceptions(std::ios_base::failbit | std::ios_base::badbit); + return formatter, Char>::format( + {buffer.data(), buffer.size()}, ctx); + } +}; + +using ostream_formatter = basic_ostream_formatter; + +template +struct formatter, Char> + : basic_ostream_formatter { + template + auto format(detail::streamed_view view, Context& ctx) const + -> decltype(ctx.out()) { + return basic_ostream_formatter::format(view.value, ctx); + } +}; + +/** + * Returns a view that formats `value` via an ostream `operator<<`. + * + * **Example**: + * + * fmt::print("Current thread id: {}\n", + * fmt::streamed(std::this_thread::get_id())); + */ +template +constexpr auto streamed(const T& value) -> detail::streamed_view { + return {value}; +} + +inline void vprint(std::ostream& os, string_view fmt, format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + FILE* f = nullptr; +#if FMT_MSVC_STL_UPDATE && FMT_USE_RTTI + if (auto* buf = dynamic_cast(os.rdbuf())) + f = detail::get_file(*buf); +#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI + auto* rdbuf = os.rdbuf(); + if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) + f = sfbuf->file(); + else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) + f = fbuf->file(); +#endif +#ifdef _WIN32 + if (f) { + int fd = _fileno(f); + if (_isatty(fd)) { + os.flush(); + if (detail::write_console(fd, {buffer.data(), buffer.size()})) return; + } + } +#endif + detail::ignore_unused(f); + detail::write_buffer(os, buffer); +} + +/** + * Prints formatted data to the stream `os`. + * + * **Example**: + * + * fmt::print(cerr, "Don't {}!", "panic"); + */ +FMT_EXPORT template +void print(std::ostream& os, format_string fmt, T&&... args) { + fmt::vargs vargs = {{args...}}; + if (detail::const_check(detail::use_utf8)) return vprint(os, fmt.str, vargs); + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt.str, vargs); + detail::write_buffer(os, buffer); +} + +FMT_EXPORT template +void println(std::ostream& os, format_string fmt, T&&... args) { + fmt::print(os, FMT_STRING("{}\n"), + fmt::format(fmt, std::forward(args)...)); +} + +FMT_END_NAMESPACE + +#endif // FMT_OSTREAM_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/printf.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/printf.h new file mode 100755 index 0000000000000000000000000000000000000000..e72684018546b60ba98ef98f5e6a0333675507c5 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/printf.h @@ -0,0 +1,633 @@ +// Formatting library for C++ - legacy printf implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_PRINTF_H_ +#define FMT_PRINTF_H_ + +#ifndef FMT_MODULE +# include // std::max +# include // std::numeric_limits +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +template struct printf_formatter { + printf_formatter() = delete; +}; + +template class basic_printf_context { + private: + basic_appender out_; + basic_format_args args_; + + static_assert(std::is_same::value || + std::is_same::value, + "Unsupported code unit type."); + + public: + using char_type = Char; + using parse_context_type = parse_context; + template using formatter_type = printf_formatter; + enum { builtin_types = 1 }; + + /// Constructs a `printf_context` object. References to the arguments are + /// stored in the context object so make sure they have appropriate lifetimes. + basic_printf_context(basic_appender out, + basic_format_args args) + : out_(out), args_(args) {} + + auto out() -> basic_appender { return out_; } + void advance_to(basic_appender) {} + + auto locale() -> detail::locale_ref { return {}; } + + auto arg(int id) const -> basic_format_arg { + return args_.get(id); + } +}; + +namespace detail { + +// Return the result via the out param to workaround gcc bug 77539. +template +FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { + for (out = first; out != last; ++out) { + if (*out == value) return true; + } + return false; +} + +template <> +inline auto find(const char* first, const char* last, char value, + const char*& out) -> bool { + out = + static_cast(memchr(first, value, to_unsigned(last - first))); + return out != nullptr; +} + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template struct int_checker { + template static auto fits_in_int(T value) -> bool { + unsigned max = to_unsigned(max_value()); + return value <= max; + } + inline static auto fits_in_int(bool) -> bool { return true; } +}; + +template <> struct int_checker { + template static auto fits_in_int(T value) -> bool { + return value >= (std::numeric_limits::min)() && + value <= max_value(); + } + inline static auto fits_in_int(int) -> bool { return true; } +}; + +struct printf_precision_handler { + template ::value)> + auto operator()(T value) -> int { + if (!int_checker::is_signed>::fits_in_int(value)) + report_error("number is too big"); + return (std::max)(static_cast(value), 0); + } + + template ::value)> + auto operator()(T) -> int { + report_error("precision is not integer"); + return 0; + } +}; + +// An argument visitor that returns true iff arg is a zero integer. +struct is_zero_int { + template ::value)> + auto operator()(T value) -> bool { + return value == 0; + } + + template ::value)> + auto operator()(T) -> bool { + return false; + } +}; + +template struct make_unsigned_or_bool : std::make_unsigned {}; + +template <> struct make_unsigned_or_bool { + using type = bool; +}; + +template class arg_converter { + private: + using char_type = typename Context::char_type; + + basic_format_arg& arg_; + char_type type_; + + public: + arg_converter(basic_format_arg& arg, char_type type) + : arg_(arg), type_(type) {} + + void operator()(bool value) { + if (type_ != 's') operator()(value); + } + + template ::value)> + void operator()(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using target_type = conditional_t::value, U, T>; + if (const_check(sizeof(target_type) <= sizeof(int))) { + // Extra casts are used to silence warnings. + using unsigned_type = typename make_unsigned_or_bool::type; + if (is_signed) + arg_ = static_cast(static_cast(value)); + else + arg_ = static_cast(static_cast(value)); + } else { + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + if (is_signed) + arg_ = static_cast(value); + else + arg_ = static_cast::type>(value); + } + } + + template ::value)> + void operator()(U) {} // No conversion needed for non-integral types. +}; + +// Converts an integer argument to T for printf, if T is an integral type. +// If T is void, the argument is converted to corresponding signed or unsigned +// type depending on the type specifier: 'd' and 'i' - signed, other - +// unsigned). +template +void convert_arg(basic_format_arg& arg, Char type) { + arg.visit(arg_converter(arg, type)); +} + +// Converts an integer argument to char for printf. +template class char_converter { + private: + basic_format_arg& arg_; + + public: + explicit char_converter(basic_format_arg& arg) : arg_(arg) {} + + template ::value)> + void operator()(T value) { + arg_ = static_cast(value); + } + + template ::value)> + void operator()(T) {} // No conversion needed for non-integral types. +}; + +// An argument visitor that return a pointer to a C string if argument is a +// string or null otherwise. +template struct get_cstring { + template auto operator()(T) -> const Char* { return nullptr; } + auto operator()(const Char* s) -> const Char* { return s; } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class printf_width_handler { + private: + format_specs& specs_; + + public: + inline explicit printf_width_handler(format_specs& specs) : specs_(specs) {} + + template ::value)> + auto operator()(T value) -> unsigned { + auto width = static_cast>(value); + if (detail::is_negative(value)) { + specs_.set_align(align::left); + width = 0 - width; + } + unsigned int_max = to_unsigned(max_value()); + if (width > int_max) report_error("number is too big"); + return static_cast(width); + } + + template ::value)> + auto operator()(T) -> unsigned { + report_error("width is not integer"); + return 0; + } +}; + +// Workaround for a bug with the XL compiler when initializing +// printf_arg_formatter's base class. +template +auto make_arg_formatter(basic_appender iter, format_specs& s) + -> arg_formatter { + return {iter, s, locale_ref()}; +} + +// The `printf` argument formatter. +template +class printf_arg_formatter : public arg_formatter { + private: + using base = arg_formatter; + using context_type = basic_printf_context; + + context_type& context_; + + void write_null_pointer(bool is_string = false) { + auto s = this->specs; + s.set_type(presentation_type::none); + write_bytes(this->out, is_string ? "(null)" : "(nil)", s); + } + + template void write(T value) { + detail::write(this->out, value, this->specs, this->locale); + } + + public: + printf_arg_formatter(basic_appender iter, format_specs& s, + context_type& ctx) + : base(make_arg_formatter(iter, s)), context_(ctx) {} + + void operator()(monostate value) { write(value); } + + template ::value)> + void operator()(T value) { + // MSVC2013 fails to compile separate overloads for bool and Char so use + // std::is_same instead. + if (!std::is_same::value) { + write(value); + return; + } + format_specs s = this->specs; + if (s.type() != presentation_type::none && + s.type() != presentation_type::chr) { + return (*this)(static_cast(value)); + } + s.set_sign(sign::none); + s.clear_alt(); + s.set_fill(' '); // Ignore '0' flag for char types. + // align::numeric needs to be overwritten here since the '0' flag is + // ignored for non-numeric types + if (s.align() == align::none || s.align() == align::numeric) + s.set_align(align::right); + detail::write(this->out, static_cast(value), s); + } + + template ::value)> + void operator()(T value) { + write(value); + } + + void operator()(const char* value) { + if (value) + write(value); + else + write_null_pointer(this->specs.type() != presentation_type::pointer); + } + + void operator()(const wchar_t* value) { + if (value) + write(value); + else + write_null_pointer(this->specs.type() != presentation_type::pointer); + } + + void operator()(basic_string_view value) { write(value); } + + void operator()(const void* value) { + if (value) + write(value); + else + write_null_pointer(); + } + + void operator()(typename basic_format_arg::handle handle) { + auto parse_ctx = parse_context({}); + handle.format(parse_ctx, context_); + } +}; + +template +void parse_flags(format_specs& specs, const Char*& it, const Char* end) { + for (; it != end; ++it) { + switch (*it) { + case '-': specs.set_align(align::left); break; + case '+': specs.set_sign(sign::plus); break; + case '0': specs.set_fill('0'); break; + case ' ': + if (specs.sign() != sign::plus) specs.set_sign(sign::space); + break; + case '#': specs.set_alt(); break; + default: return; + } + } +} + +template +auto parse_header(const Char*& it, const Char* end, format_specs& specs, + GetArg get_arg) -> int { + int arg_index = -1; + Char c = *it; + if (c >= '0' && c <= '9') { + // Parse an argument index (if followed by '$') or a width possibly + // preceded with '0' flag(s). + int value = parse_nonnegative_int(it, end, -1); + if (it != end && *it == '$') { // value is an argument index + ++it; + arg_index = value != -1 ? value : max_value(); + } else { + if (c == '0') specs.set_fill('0'); + if (value != 0) { + // Nonzero value means that we parsed width and don't need to + // parse it or flags again, so return now. + if (value == -1) report_error("number is too big"); + specs.width = value; + return arg_index; + } + } + } + parse_flags(specs, it, end); + // Parse width. + if (it != end) { + if (*it >= '0' && *it <= '9') { + specs.width = parse_nonnegative_int(it, end, -1); + if (specs.width == -1) report_error("number is too big"); + } else if (*it == '*') { + ++it; + specs.width = static_cast( + get_arg(-1).visit(detail::printf_width_handler(specs))); + } + } + return arg_index; +} + +inline auto parse_printf_presentation_type(char c, type t, bool& upper) + -> presentation_type { + using pt = presentation_type; + constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; + switch (c) { + case 'd': return in(t, integral_set) ? pt::dec : pt::none; + case 'o': return in(t, integral_set) ? pt::oct : pt::none; + case 'X': upper = true; FMT_FALLTHROUGH; + case 'x': return in(t, integral_set) ? pt::hex : pt::none; + case 'E': upper = true; FMT_FALLTHROUGH; + case 'e': return in(t, float_set) ? pt::exp : pt::none; + case 'F': upper = true; FMT_FALLTHROUGH; + case 'f': return in(t, float_set) ? pt::fixed : pt::none; + case 'G': upper = true; FMT_FALLTHROUGH; + case 'g': return in(t, float_set) ? pt::general : pt::none; + case 'A': upper = true; FMT_FALLTHROUGH; + case 'a': return in(t, float_set) ? pt::hexfloat : pt::none; + case 'c': return in(t, integral_set) ? pt::chr : pt::none; + case 's': return in(t, string_set | cstring_set) ? pt::string : pt::none; + case 'p': return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none; + default: return pt::none; + } +} + +template +void vprintf(buffer& buf, basic_string_view format, + basic_format_args args) { + using iterator = basic_appender; + auto out = iterator(buf); + auto context = basic_printf_context(out, args); + auto parse_ctx = parse_context(format); + + // Returns the argument with specified index or, if arg_index is -1, the next + // argument. + auto get_arg = [&](int arg_index) { + if (arg_index < 0) + arg_index = parse_ctx.next_arg_id(); + else + parse_ctx.check_arg_id(--arg_index); + return detail::get_arg(context, arg_index); + }; + + const Char* start = parse_ctx.begin(); + const Char* end = parse_ctx.end(); + auto it = start; + while (it != end) { + if (!find(it, end, '%', it)) { + it = end; // find leaves it == nullptr if it doesn't find '%'. + break; + } + Char c = *it++; + if (it != end && *it == c) { + write(out, basic_string_view(start, to_unsigned(it - start))); + start = ++it; + continue; + } + write(out, basic_string_view(start, to_unsigned(it - 1 - start))); + + auto specs = format_specs(); + specs.set_align(align::right); + + // Parse argument index, flags and width. + int arg_index = parse_header(it, end, specs, get_arg); + if (arg_index == 0) report_error("argument not found"); + + // Parse precision. + if (it != end && *it == '.') { + ++it; + c = it != end ? *it : 0; + if ('0' <= c && c <= '9') { + specs.precision = parse_nonnegative_int(it, end, 0); + } else if (c == '*') { + ++it; + specs.precision = + static_cast(get_arg(-1).visit(printf_precision_handler())); + } else { + specs.precision = 0; + } + } + + auto arg = get_arg(arg_index); + // For d, i, o, u, x, and X conversion specifiers, if a precision is + // specified, the '0' flag is ignored + if (specs.precision >= 0 && is_integral_type(arg.type())) { + // Ignore '0' for non-numeric types or if '-' present. + specs.set_fill(' '); + } + if (specs.precision >= 0 && arg.type() == type::cstring_type) { + auto str = arg.visit(get_cstring()); + auto str_end = str + specs.precision; + auto nul = std::find(str, str_end, Char()); + auto sv = basic_string_view( + str, to_unsigned(nul != str_end ? nul - str : specs.precision)); + arg = sv; + } + if (specs.alt() && arg.visit(is_zero_int())) specs.clear_alt(); + if (specs.fill_unit() == '0') { + if (is_arithmetic_type(arg.type()) && specs.align() != align::left) { + specs.set_align(align::numeric); + } else { + // Ignore '0' flag for non-numeric types or if '-' flag is also present. + specs.set_fill(' '); + } + } + + // Parse length and convert the argument to the required type. + c = it != end ? *it++ : 0; + Char t = it != end ? *it : 0; + switch (c) { + case 'h': + if (t == 'h') { + ++it; + t = it != end ? *it : 0; + convert_arg(arg, t); + } else { + convert_arg(arg, t); + } + break; + case 'l': + if (t == 'l') { + ++it; + t = it != end ? *it : 0; + convert_arg(arg, t); + } else { + convert_arg(arg, t); + } + break; + case 'j': convert_arg(arg, t); break; + case 'z': convert_arg(arg, t); break; + case 't': convert_arg(arg, t); break; + case 'L': + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. + break; + default: --it; convert_arg(arg, c); + } + + // Parse type. + if (it == end) report_error("invalid format string"); + char type = static_cast(*it++); + if (is_integral_type(arg.type())) { + // Normalize type. + switch (type) { + case 'i': + case 'u': type = 'd'; break; + case 'c': + arg.visit(char_converter>(arg)); + break; + } + } + bool upper = false; + specs.set_type(parse_printf_presentation_type(type, arg.type(), upper)); + if (specs.type() == presentation_type::none) + report_error("invalid format specifier"); + if (upper) specs.set_upper(); + + start = it; + + // Format argument. + arg.visit(printf_arg_formatter(out, specs, context)); + } + write(out, basic_string_view(start, to_unsigned(it - start))); +} +} // namespace detail + +using printf_context = basic_printf_context; +using wprintf_context = basic_printf_context; + +using printf_args = basic_format_args; +using wprintf_args = basic_format_args; + +/// Constructs an `format_arg_store` object that contains references to +/// arguments and can be implicitly converted to `printf_args`. +template +inline auto make_printf_args(T&... args) + -> decltype(fmt::make_format_args>(args...)) { + return fmt::make_format_args>(args...); +} + +template struct vprintf_args { + using type = basic_format_args>; +}; + +template +inline auto vsprintf(basic_string_view fmt, + typename vprintf_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vprintf(buf, fmt, args); + return {buf.data(), buf.size()}; +} + +/** + * Formats `args` according to specifications in `fmt` and returns the result + * as as string. + * + * **Example**: + * + * std::string message = fmt::sprintf("The answer is %d", 42); + */ +template > +inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string { + return vsprintf(detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template +inline auto vfprintf(std::FILE* f, basic_string_view fmt, + typename vprintf_args::type args) -> int { + auto buf = basic_memory_buffer(); + detail::vprintf(buf, fmt, args); + size_t size = buf.size(); + return std::fwrite(buf.data(), sizeof(Char), size, f) < size + ? -1 + : static_cast(size); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `f`. + * + * **Example**: + * + * fmt::fprintf(stderr, "Don't %s!", "panic"); + */ +template > +inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { + return vfprintf(f, detail::to_string_view(fmt), + make_printf_args(args...)); +} + +template +FMT_DEPRECATED inline auto vprintf(basic_string_view fmt, + typename vprintf_args::type args) + -> int { + return vfprintf(stdout, fmt, args); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::printf("Elapsed time: %.2f seconds", 1.23); + */ +template +inline auto printf(string_view fmt, const T&... args) -> int { + return vfprintf(stdout, fmt, make_printf_args(args...)); +} +template +FMT_DEPRECATED inline auto printf(basic_string_view fmt, + const T&... args) -> int { + return vfprintf(stdout, fmt, make_printf_args(args...)); +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_PRINTF_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/ranges.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/ranges.h new file mode 100755 index 0000000000000000000000000000000000000000..23ff7de09131e7922a6a04fbc5428a3fe928688f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/ranges.h @@ -0,0 +1,850 @@ +// Formatting library for C++ - range and tuple support +// +// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_RANGES_H_ +#define FMT_RANGES_H_ + +#ifndef FMT_MODULE +# include +# include +# include +# include +# include +# include +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +FMT_EXPORT +enum class range_format { disabled, map, set, sequence, string, debug_string }; + +namespace detail { + +template class is_map { + template static auto check(U*) -> typename U::mapped_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +template class is_set { + template static auto check(U*) -> typename U::key_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value && !is_map::value; +}; + +// C array overload +template +auto range_begin(const T (&arr)[N]) -> const T* { + return arr; +} +template +auto range_end(const T (&arr)[N]) -> const T* { + return arr + N; +} + +template +struct has_member_fn_begin_end_t : std::false_type {}; + +template +struct has_member_fn_begin_end_t().begin()), + decltype(std::declval().end())>> + : std::true_type {}; + +// Member function overloads. +template +auto range_begin(T&& rng) -> decltype(static_cast(rng).begin()) { + return static_cast(rng).begin(); +} +template +auto range_end(T&& rng) -> decltype(static_cast(rng).end()) { + return static_cast(rng).end(); +} + +// ADL overloads. Only participate in overload resolution if member functions +// are not found. +template +auto range_begin(T&& rng) + -> enable_if_t::value, + decltype(begin(static_cast(rng)))> { + return begin(static_cast(rng)); +} +template +auto range_end(T&& rng) -> enable_if_t::value, + decltype(end(static_cast(rng)))> { + return end(static_cast(rng)); +} + +template +struct has_const_begin_end : std::false_type {}; +template +struct has_mutable_begin_end : std::false_type {}; + +template +struct has_const_begin_end< + T, void_t&>())), + decltype(detail::range_end( + std::declval&>()))>> + : std::true_type {}; + +template +struct has_mutable_begin_end< + T, void_t())), + decltype(detail::range_end(std::declval())), + // the extra int here is because older versions of MSVC don't + // SFINAE properly unless there are distinct types + int>> : std::true_type {}; + +template struct is_range_ : std::false_type {}; +template +struct is_range_ + : std::integral_constant::value || + has_mutable_begin_end::value)> {}; + +// tuple_size and tuple_element check. +template class is_tuple_like_ { + template ::type> + static auto check(U* p) -> decltype(std::tuple_size::value, 0); + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +// Check for integer_sequence +#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900 +template +using integer_sequence = std::integer_sequence; +template using index_sequence = std::index_sequence; +template using make_index_sequence = std::make_index_sequence; +#else +template struct integer_sequence { + using value_type = T; + + static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); } +}; + +template using index_sequence = integer_sequence; + +template +struct make_integer_sequence : make_integer_sequence {}; +template +struct make_integer_sequence : integer_sequence {}; + +template +using make_index_sequence = make_integer_sequence; +#endif + +template +using tuple_index_sequence = make_index_sequence::value>; + +template ::value> +class is_tuple_formattable_ { + public: + static constexpr const bool value = false; +}; +template class is_tuple_formattable_ { + template + static auto all_true(index_sequence, + integer_sequence= 0)...>) -> std::true_type; + static auto all_true(...) -> std::false_type; + + template + static auto check(index_sequence) -> decltype(all_true( + index_sequence{}, + integer_sequence::type, + C>::value)...>{})); + + public: + static constexpr const bool value = + decltype(check(tuple_index_sequence{}))::value; +}; + +template +FMT_CONSTEXPR void for_each(index_sequence, Tuple&& t, F&& f) { + using std::get; + // Using a free function get(Tuple) now. + const int unused[] = {0, ((void)f(get(t)), 0)...}; + ignore_unused(unused); +} + +template +FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) { + for_each(tuple_index_sequence>(), + std::forward(t), std::forward(f)); +} + +template +void for_each2(index_sequence, Tuple1&& t1, Tuple2&& t2, F&& f) { + using std::get; + const int unused[] = {0, ((void)f(get(t1), get(t2)), 0)...}; + ignore_unused(unused); +} + +template +void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) { + for_each2(tuple_index_sequence>(), + std::forward(t1), std::forward(t2), + std::forward(f)); +} + +namespace tuple { +// Workaround a bug in MSVC 2019 (v140). +template +using result_t = std::tuple, Char>...>; + +using std::get; +template +auto get_formatters(index_sequence) + -> result_t(std::declval()))...>; +} // namespace tuple + +#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920 +// Older MSVC doesn't get the reference type correctly for arrays. +template struct range_reference_type_impl { + using type = decltype(*detail::range_begin(std::declval())); +}; + +template struct range_reference_type_impl { + using type = T&; +}; + +template +using range_reference_type = typename range_reference_type_impl::type; +#else +template +using range_reference_type = + decltype(*detail::range_begin(std::declval())); +#endif + +// We don't use the Range's value_type for anything, but we do need the Range's +// reference type, with cv-ref stripped. +template +using uncvref_type = remove_cvref_t>; + +template +FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set) + -> decltype(f.set_debug_format(set)) { + f.set_debug_format(set); +} +template +FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {} + +template +struct range_format_kind_ + : std::integral_constant, T>::value + ? range_format::disabled + : is_map::value ? range_format::map + : is_set::value ? range_format::set + : range_format::sequence> {}; + +template +using range_format_constant = std::integral_constant; + +// These are not generic lambdas for compatibility with C++11. +template struct parse_empty_specs { + template FMT_CONSTEXPR void operator()(Formatter& f) { + f.parse(ctx); + detail::maybe_set_debug_format(f, true); + } + parse_context& ctx; +}; +template struct format_tuple_element { + using char_type = typename FormatContext::char_type; + + template + void operator()(const formatter& f, const T& v) { + if (i > 0) ctx.advance_to(detail::copy(separator, ctx.out())); + ctx.advance_to(f.format(v, ctx)); + ++i; + } + + int i; + FormatContext& ctx; + basic_string_view separator; +}; + +} // namespace detail + +template struct is_tuple_like { + static constexpr const bool value = + detail::is_tuple_like_::value && !detail::is_range_::value; +}; + +template struct is_tuple_formattable { + static constexpr const bool value = + detail::is_tuple_formattable_::value; +}; + +template +struct formatter::value && + fmt::is_tuple_formattable::value>> { + private: + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + + public: + FMT_CONSTEXPR formatter() {} + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(); + auto end = ctx.end(); + if (it != end && detail::to_ascii(*it) == 'n') { + ++it; + set_brackets({}, {}); + set_separator({}); + } + if (it != end && *it != '}') report_error("invalid format specifier"); + ctx.advance_to(it); + detail::for_each(formatters_, detail::parse_empty_specs{ctx}); + return it; + } + + template + auto format(const Tuple& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + ctx.advance_to(detail::copy(opening_bracket_, ctx.out())); + detail::for_each2( + formatters_, value, + detail::format_tuple_element{0, ctx, separator_}); + return detail::copy(closing_bracket_, ctx.out()); + } +}; + +template struct is_range { + static constexpr const bool value = + detail::is_range_::value && !detail::has_to_string_view::value; +}; + +namespace detail { + +template +using range_formatter_type = formatter, Char>; + +template +using maybe_const_range = + conditional_t::value, const R, R>; + +template +struct is_formattable_delayed + : is_formattable>, Char> {}; +} // namespace detail + +template struct conjunction : std::true_type {}; +template struct conjunction

: P {}; +template +struct conjunction + : conditional_t, P1> {}; + +template +struct range_formatter; + +template +struct range_formatter< + T, Char, + enable_if_t>, + is_formattable>::value>> { + private: + detail::range_formatter_type underlying_; + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + bool is_debug = false; + + template ::value)> + auto write_debug_string(Output& out, It it, Sentinel end) const -> Output { + auto buf = basic_memory_buffer(); + for (; it != end; ++it) buf.push_back(*it); + auto specs = format_specs(); + specs.set_type(presentation_type::debug); + return detail::write( + out, basic_string_view(buf.data(), buf.size()), specs); + } + + template ::value)> + auto write_debug_string(Output& out, It, Sentinel) const -> Output { + return out; + } + + public: + FMT_CONSTEXPR range_formatter() {} + + FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type& { + return underlying_; + } + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(); + auto end = ctx.end(); + detail::maybe_set_debug_format(underlying_, true); + if (it == end) return underlying_.parse(ctx); + + switch (detail::to_ascii(*it)) { + case 'n': + set_brackets({}, {}); + ++it; + break; + case '?': + is_debug = true; + set_brackets({}, {}); + ++it; + if (it == end || *it != 's') report_error("invalid format specifier"); + FMT_FALLTHROUGH; + case 's': + if (!std::is_same::value) + report_error("invalid format specifier"); + if (!is_debug) { + set_brackets(detail::string_literal{}, + detail::string_literal{}); + set_separator({}); + detail::maybe_set_debug_format(underlying_, false); + } + ++it; + return it; + } + + if (it != end && *it != '}') { + if (*it != ':') report_error("invalid format specifier"); + detail::maybe_set_debug_format(underlying_, false); + ++it; + } + + ctx.advance_to(it); + return underlying_.parse(ctx); + } + + template + auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) { + auto out = ctx.out(); + auto it = detail::range_begin(range); + auto end = detail::range_end(range); + if (is_debug) return write_debug_string(out, std::move(it), end); + + out = detail::copy(opening_bracket_, out); + int i = 0; + for (; it != end; ++it) { + if (i > 0) out = detail::copy(separator_, out); + ctx.advance_to(out); + auto&& item = *it; // Need an lvalue + out = underlying_.format(item, ctx); + ++i; + } + out = detail::copy(closing_bracket_, out); + return out; + } +}; + +FMT_EXPORT +template +struct range_format_kind + : conditional_t< + is_range::value, detail::range_format_kind_, + std::integral_constant> {}; + +template +struct formatter< + R, Char, + enable_if_t::value != range_format::disabled && + range_format_kind::value != range_format::map && + range_format_kind::value != range_format::string && + range_format_kind::value != range_format::debug_string>, + detail::is_formattable_delayed>::value>> { + private: + using range_type = detail::maybe_const_range; + range_formatter, Char> range_formatter_; + + public: + using nonlocking = void; + + FMT_CONSTEXPR formatter() { + if (detail::const_check(range_format_kind::value != + range_format::set)) + return; + range_formatter_.set_brackets(detail::string_literal{}, + detail::string_literal{}); + } + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return range_formatter_.parse(ctx); + } + + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + return range_formatter_.format(range, ctx); + } +}; + +// A map formatter. +template +struct formatter< + R, Char, + enable_if_t::value == range_format::map>, + detail::is_formattable_delayed>::value>> { + private: + using map_type = detail::maybe_const_range; + using element_type = detail::uncvref_type; + + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + bool no_delimiters_ = false; + + public: + FMT_CONSTEXPR formatter() {} + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(); + auto end = ctx.end(); + if (it != end) { + if (detail::to_ascii(*it) == 'n') { + no_delimiters_ = true; + ++it; + } + if (it != end && *it != '}') { + if (*it != ':') report_error("invalid format specifier"); + ++it; + } + ctx.advance_to(it); + } + detail::for_each(formatters_, detail::parse_empty_specs{ctx}); + return it; + } + + template + auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) { + auto out = ctx.out(); + basic_string_view open = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(open, out); + int i = 0; + basic_string_view sep = detail::string_literal{}; + for (auto&& value : map) { + if (i > 0) out = detail::copy(sep, out); + ctx.advance_to(out); + detail::for_each2(formatters_, value, + detail::format_tuple_element{ + 0, ctx, detail::string_literal{}}); + ++i; + } + basic_string_view close = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(close, out); + return out; + } +}; + +// A (debug_)string formatter. +template +struct formatter< + R, Char, + enable_if_t::value == range_format::string || + range_format_kind::value == + range_format::debug_string>> { + private: + using range_type = detail::maybe_const_range; + using string_type = + conditional_t, + decltype(detail::range_begin(std::declval())), + decltype(detail::range_end(std::declval()))>::value, + detail::std_string_view, std::basic_string>; + + formatter underlying_; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return underlying_.parse(ctx); + } + + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + out = underlying_.format( + string_type{detail::range_begin(range), detail::range_end(range)}, ctx); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + return out; + } +}; + +template +struct join_view : detail::view { + It begin; + Sentinel end; + basic_string_view sep; + + join_view(It b, Sentinel e, basic_string_view s) + : begin(std::move(b)), end(e), sep(s) {} +}; + +template +struct formatter, Char> { + private: + using value_type = +#ifdef __cpp_lib_ranges + std::iter_value_t; +#else + typename std::iterator_traits::value_type; +#endif + formatter, Char> value_formatter_; + + using view = conditional_t::value, + const join_view, + join_view>; + + public: + using nonlocking = void; + + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return value_formatter_.parse(ctx); + } + + template + auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) { + using iter = + conditional_t::value, It, It&>; + iter it = value.begin; + auto out = ctx.out(); + if (it == value.end) return out; + out = value_formatter_.format(*it, ctx); + ++it; + while (it != value.end) { + out = detail::copy(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); + out = value_formatter_.format(*it, ctx); + ++it; + } + return out; + } +}; + +template struct tuple_join_view : detail::view { + const Tuple& tuple; + basic_string_view sep; + + tuple_join_view(const Tuple& t, basic_string_view s) + : tuple(t), sep{s} {} +}; + +// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers +// support in tuple_join. It is disabled by default because of issues with +// the dynamic width and precision. +#ifndef FMT_TUPLE_JOIN_SPECIFIERS +# define FMT_TUPLE_JOIN_SPECIFIERS 0 +#endif + +template +struct formatter, Char, + enable_if_t::value>> { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return do_parse(ctx, std::tuple_size()); + } + + template + auto format(const tuple_join_view& value, + FormatContext& ctx) const -> typename FormatContext::iterator { + return do_format(value, ctx, std::tuple_size()); + } + + private: + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + + FMT_CONSTEXPR auto do_parse(parse_context& ctx, + std::integral_constant) + -> const Char* { + return ctx.begin(); + } + + template + FMT_CONSTEXPR auto do_parse(parse_context& ctx, + std::integral_constant) + -> const Char* { + auto end = ctx.begin(); +#if FMT_TUPLE_JOIN_SPECIFIERS + end = std::get::value - N>(formatters_).parse(ctx); + if (N > 1) { + auto end1 = do_parse(ctx, std::integral_constant()); + if (end != end1) + report_error("incompatible format specs for tuple elements"); + } +#endif + return end; + } + + template + auto do_format(const tuple_join_view&, FormatContext& ctx, + std::integral_constant) const -> + typename FormatContext::iterator { + return ctx.out(); + } + + template + auto do_format(const tuple_join_view& value, FormatContext& ctx, + std::integral_constant) const -> + typename FormatContext::iterator { + using std::get; + auto out = + std::get::value - N>(formatters_) + .format(get::value - N>(value.tuple), ctx); + if (N <= 1) return out; + out = detail::copy(value.sep, out); + ctx.advance_to(out); + return do_format(value, ctx, std::integral_constant()); + } +}; + +namespace detail { +// Check if T has an interface like a container adaptor (e.g. std::stack, +// std::queue, std::priority_queue). +template class is_container_adaptor_like { + template static auto check(U* p) -> typename U::container_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +template struct all { + const Container& c; + auto begin() const -> typename Container::const_iterator { return c.begin(); } + auto end() const -> typename Container::const_iterator { return c.end(); } +}; +} // namespace detail + +template +struct formatter< + T, Char, + enable_if_t, + bool_constant::value == + range_format::disabled>>::value>> + : formatter, Char> { + using all = detail::all; + template + auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { + struct getter : T { + static auto get(const T& v) -> all { + return {v.*(&getter::c)}; // Access c through the derived class. + } + }; + return formatter::format(getter::get(value), ctx); + } +}; + +FMT_BEGIN_EXPORT + +/// Returns a view that formats the iterator range `[begin, end)` with elements +/// separated by `sep`. +template +auto join(It begin, Sentinel end, string_view sep) -> join_view { + return {std::move(begin), end, sep}; +} + +/** + * Returns a view that formats `range` with elements separated by `sep`. + * + * **Example**: + * + * auto v = std::vector{1, 2, 3}; + * fmt::print("{}", fmt::join(v, ", ")); + * // Output: 1, 2, 3 + * + * `fmt::join` applies passed format specifiers to the range elements: + * + * fmt::print("{:02}", fmt::join(v, ", ")); + * // Output: 01, 02, 03 + */ +template ::value)> +auto join(Range&& r, string_view sep) + -> join_view { + return {detail::range_begin(r), detail::range_end(r), sep}; +} + +/** + * Returns an object that formats `std::tuple` with elements separated by `sep`. + * + * **Example**: + * + * auto t = std::tuple{1, 'a'}; + * fmt::print("{}", fmt::join(t, ", ")); + * // Output: 1, a + */ +template ::value)> +FMT_CONSTEXPR auto join(const Tuple& tuple, string_view sep) + -> tuple_join_view { + return {tuple, sep}; +} + +/** + * Returns an object that formats `std::initializer_list` with elements + * separated by `sep`. + * + * **Example**: + * + * fmt::print("{}", fmt::join({1, 2, 3}, ", ")); + * // Output: "1, 2, 3" + */ +template +auto join(std::initializer_list list, string_view sep) + -> join_view { + return join(std::begin(list), std::end(list), sep); +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_RANGES_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/std.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/std.h new file mode 100755 index 0000000000000000000000000000000000000000..f43dc74d21c9caee0803b8d4f13b2f7b4fccad4b --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/std.h @@ -0,0 +1,728 @@ +// Formatting library for C++ - formatters for standard library types +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_STD_H_ +#define FMT_STD_H_ + +#include "format.h" +#include "ostream.h" + +#ifndef FMT_MODULE +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC. +# if FMT_CPLUSPLUS >= 201703L +# if FMT_HAS_INCLUDE() && \ + (!defined(FMT_CPP_LIB_FILESYSTEM) || FMT_CPP_LIB_FILESYSTEM != 0) +# include +# endif +# if FMT_HAS_INCLUDE() +# include +# endif +# if FMT_HAS_INCLUDE() +# include +# endif +# endif +// Use > instead of >= in the version check because may be +// available after C++17 but before C++20 is marked as implemented. +# if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE() +# include +# endif +# if FMT_CPLUSPLUS > 202002L && FMT_HAS_INCLUDE() +# include +# endif +#endif // FMT_MODULE + +#if FMT_HAS_INCLUDE() +# include +#endif + +// GCC 4 does not support FMT_HAS_INCLUDE. +#if FMT_HAS_INCLUDE() || defined(__GLIBCXX__) +# include +// Android NDK with gabi++ library on some architectures does not implement +// abi::__cxa_demangle(). +# ifndef __GABIXX_CXXABI_H__ +# define FMT_HAS_ABI_CXA_DEMANGLE +# endif +#endif + +// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined. +#ifndef FMT_CPP_LIB_FILESYSTEM +# ifdef __cpp_lib_filesystem +# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem +# else +# define FMT_CPP_LIB_FILESYSTEM 0 +# endif +#endif + +#ifndef FMT_CPP_LIB_VARIANT +# ifdef __cpp_lib_variant +# define FMT_CPP_LIB_VARIANT __cpp_lib_variant +# else +# define FMT_CPP_LIB_VARIANT 0 +# endif +#endif + +#if FMT_CPP_LIB_FILESYSTEM +FMT_BEGIN_NAMESPACE + +namespace detail { + +template +auto get_path_string(const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && std::is_same_v) + return to_utf8(native, to_utf8_error_policy::replace); + else + return p.string(); +} + +template +void write_escaped_path(basic_memory_buffer& quoted, + const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && + std::is_same_v) { + auto buf = basic_memory_buffer(); + write_escaped_string(std::back_inserter(buf), native); + bool valid = to_utf8::convert(quoted, {buf.data(), buf.size()}); + FMT_ASSERT(valid, "invalid utf16"); + } else if constexpr (std::is_same_v) { + write_escaped_string( + std::back_inserter(quoted), native); + } else { + write_escaped_string(std::back_inserter(quoted), p.string()); + } +} + +} // namespace detail + +template struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + bool debug_ = false; + char path_type_ = 0; + + public: + FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; } + + FMT_CONSTEXPR auto parse(parse_context& ctx) { + auto it = ctx.begin(), end = ctx.end(); + if (it == end) return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + Char c = *it; + if ((c >= '0' && c <= '9') || c == '{') + it = detail::parse_width(it, end, specs_, width_ref_, ctx); + if (it != end && *it == '?') { + debug_ = true; + ++it; + } + if (it != end && (*it == 'g')) path_type_ = detail::to_ascii(*it++); + return it; + } + + template + auto format(const std::filesystem::path& p, FormatContext& ctx) const { + auto specs = specs_; + auto path_string = + !path_type_ ? p.native() + : p.generic_string(); + + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_, + ctx); + if (!debug_) { + auto s = detail::get_path_string(p, path_string); + return detail::write(ctx.out(), basic_string_view(s), specs); + } + auto quoted = basic_memory_buffer(); + detail::write_escaped_path(quoted, p, path_string); + return detail::write(ctx.out(), + basic_string_view(quoted.data(), quoted.size()), + specs); + } +}; + +class path : public std::filesystem::path { + public: + auto display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{}"), base); + } + auto system_string() const -> std::string { return string(); } + + auto generic_display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{:g}"), base); + } + auto generic_system_string() const -> std::string { return generic_string(); } +}; + +FMT_END_NAMESPACE +#endif // FMT_CPP_LIB_FILESYSTEM + +FMT_BEGIN_NAMESPACE +template +struct formatter, Char> + : nested_formatter, Char> { + private: + // Functor because C++11 doesn't support generic lambdas. + struct writer { + const std::bitset& bs; + + template + FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt { + for (auto pos = N; pos > 0; --pos) { + out = detail::write(out, bs[pos - 1] ? Char('1') : Char('0')); + } + + return out; + } + }; + + public: + template + auto format(const std::bitset& bs, FormatContext& ctx) const + -> decltype(ctx.out()) { + return this->write_padded(ctx, writer{bs}); + } +}; + +template +struct formatter : basic_ostream_formatter {}; +FMT_END_NAMESPACE + +#ifdef __cpp_lib_optional +FMT_BEGIN_NAMESPACE +template +struct formatter, Char, + std::enable_if_t::value>> { + private: + formatter underlying_; + static constexpr basic_string_view optional = + detail::string_literal{}; + static constexpr basic_string_view none = + detail::string_literal{}; + + template + FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set) + -> decltype(u.set_debug_format(set)) { + u.set_debug_format(set); + } + + template + FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {} + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) { + maybe_set_debug_format(underlying_, true); + return underlying_.parse(ctx); + } + + template + auto format(const std::optional& opt, FormatContext& ctx) const + -> decltype(ctx.out()) { + if (!opt) return detail::write(ctx.out(), none); + + auto out = ctx.out(); + out = detail::write(out, optional); + ctx.advance_to(out); + out = underlying_.format(*opt, ctx); + return detail::write(out, ')'); + } +}; +FMT_END_NAMESPACE +#endif // __cpp_lib_optional + +#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT + +FMT_BEGIN_NAMESPACE +namespace detail { + +template +auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt { + if constexpr (has_to_string_view::value) + return write_escaped_string(out, detail::to_string_view(v)); + if constexpr (std::is_same_v) return write_escaped_char(out, v); + return write(out, v); +} + +} // namespace detail + +FMT_END_NAMESPACE +#endif + +#ifdef __cpp_lib_expected +FMT_BEGIN_NAMESPACE + +template +struct formatter, Char, + std::enable_if_t<(std::is_void::value || + is_formattable::value) && + is_formattable::value>> { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return ctx.begin(); + } + + template + auto format(const std::expected& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + + if (value.has_value()) { + out = detail::write(out, "expected("); + if constexpr (!std::is_void::value) + out = detail::write_escaped_alternative(out, *value); + } else { + out = detail::write(out, "unexpected("); + out = detail::write_escaped_alternative(out, value.error()); + } + *out++ = ')'; + return out; + } +}; +FMT_END_NAMESPACE +#endif // __cpp_lib_expected + +#ifdef __cpp_lib_source_location +FMT_BEGIN_NAMESPACE +template <> struct formatter { + FMT_CONSTEXPR auto parse(parse_context<>& ctx) { return ctx.begin(); } + + template + auto format(const std::source_location& loc, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + out = detail::write(out, loc.file_name()); + out = detail::write(out, ':'); + out = detail::write(out, loc.line()); + out = detail::write(out, ':'); + out = detail::write(out, loc.column()); + out = detail::write(out, ": "); + out = detail::write(out, loc.function_name()); + return out; + } +}; +FMT_END_NAMESPACE +#endif + +#if FMT_CPP_LIB_VARIANT +FMT_BEGIN_NAMESPACE +namespace detail { + +template +using variant_index_sequence = + std::make_index_sequence::value>; + +template struct is_variant_like_ : std::false_type {}; +template +struct is_variant_like_> : std::true_type {}; + +// formattable element check. +template class is_variant_formattable_ { + template + static std::conjunction< + is_formattable, C>...> + check(std::index_sequence); + + public: + static constexpr const bool value = + decltype(check(variant_index_sequence{}))::value; +}; + +} // namespace detail + +template struct is_variant_like { + static constexpr const bool value = detail::is_variant_like_::value; +}; + +template struct is_variant_formattable { + static constexpr const bool value = + detail::is_variant_formattable_::value; +}; + +template struct formatter { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return ctx.begin(); + } + + template + auto format(const std::monostate&, FormatContext& ctx) const + -> decltype(ctx.out()) { + return detail::write(ctx.out(), "monostate"); + } +}; + +template +struct formatter< + Variant, Char, + std::enable_if_t, is_variant_formattable>>> { + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return ctx.begin(); + } + + template + auto format(const Variant& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + + out = detail::write(out, "variant("); + FMT_TRY { + std::visit( + [&](const auto& v) { + out = detail::write_escaped_alternative(out, v); + }, + value); + } + FMT_CATCH(const std::bad_variant_access&) { + detail::write(out, "valueless by exception"); + } + *out++ = ')'; + return out; + } +}; +FMT_END_NAMESPACE +#endif // FMT_CPP_LIB_VARIANT + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + bool debug_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* { + auto it = ctx.begin(), end = ctx.end(); + if (it == end) return it; + + it = detail::parse_align(it, end, specs_); + + char c = *it; + if (it != end && ((c >= '0' && c <= '9') || c == '{')) + it = detail::parse_width(it, end, specs_, width_ref_, ctx); + + if (it != end && *it == '?') { + debug_ = true; + ++it; + } + if (it != end && *it == 's') { + specs_.set_type(presentation_type::string); + ++it; + } + return it; + } + + template + FMT_CONSTEXPR20 auto format(const std::error_code& ec, + FormatContext& ctx) const -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_, + ctx); + auto buf = memory_buffer(); + if (specs_.type() == presentation_type::string) { + buf.append(ec.message()); + } else { + buf.append(string_view(ec.category().name())); + buf.push_back(':'); + detail::write(appender(buf), ec.value()); + } + auto quoted = memory_buffer(); + auto str = string_view(buf.data(), buf.size()); + if (debug_) { + detail::write_escaped_string(std::back_inserter(quoted), str); + str = string_view(quoted.data(), quoted.size()); + } + return detail::write(ctx.out(), str, specs); + } +}; + +#if FMT_USE_RTTI +namespace detail { + +template +auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt { +# ifdef FMT_HAS_ABI_CXA_DEMANGLE + int status = 0; + std::size_t size = 0; + std::unique_ptr demangled_name_ptr( + abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); + + string_view demangled_name_view; + if (demangled_name_ptr) { + demangled_name_view = demangled_name_ptr.get(); + + // Normalization of stdlib inline namespace names. + // libc++ inline namespaces. + // std::__1::* -> std::* + // std::__1::__fs::* -> std::* + // libstdc++ inline namespaces. + // std::__cxx11::* -> std::* + // std::filesystem::__cxx11::* -> std::filesystem::* + if (demangled_name_view.starts_with("std::")) { + char* begin = demangled_name_ptr.get(); + char* to = begin + 5; // std:: + for (char *from = to, *end = begin + demangled_name_view.size(); + from < end;) { + // This is safe, because demangled_name is NUL-terminated. + if (from[0] == '_' && from[1] == '_') { + char* next = from + 1; + while (next < end && *next != ':') next++; + if (next[0] == ':' && next[1] == ':') { + from = next + 2; + continue; + } + } + *to++ = *from++; + } + demangled_name_view = {begin, detail::to_unsigned(to - begin)}; + } + } else { + demangled_name_view = string_view(ti.name()); + } + return detail::write_bytes(out, demangled_name_view); +# elif FMT_MSC_VERSION + const string_view demangled_name(ti.name()); + for (std::size_t i = 0; i < demangled_name.size(); ++i) { + auto sub = demangled_name; + sub.remove_prefix(i); + if (sub.starts_with("enum ")) { + i += 4; + continue; + } + if (sub.starts_with("class ") || sub.starts_with("union ")) { + i += 5; + continue; + } + if (sub.starts_with("struct ")) { + i += 6; + continue; + } + if (*sub.begin() != ' ') *out++ = *sub.begin(); + } + return out; +# else + return detail::write_bytes(out, string_view(ti.name())); +# endif +} + +} // namespace detail + +template +struct formatter { + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + return ctx.begin(); + } + + template + auto format(const std::type_info& ti, Context& ctx) const + -> decltype(ctx.out()) { + return detail::write_demangled_name(ctx.out(), ti); + } +}; +#endif + +template +struct formatter< + T, Char, // DEPRECATED! Mixing code unit types. + typename std::enable_if::value>::type> { + private: + bool with_typename_ = false; + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + auto it = ctx.begin(); + auto end = ctx.end(); + if (it == end || *it == '}') return it; + if (*it == 't') { + ++it; + with_typename_ = FMT_USE_RTTI != 0; + } + return it; + } + + template + auto format(const std::exception& ex, Context& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); +#if FMT_USE_RTTI + if (with_typename_) { + out = detail::write_demangled_name(out, typeid(ex)); + *out++ = ':'; + *out++ = ' '; + } +#endif + return detail::write_bytes(out, string_view(ex.what())); + } +}; + +namespace detail { + +template +struct has_flip : std::false_type {}; + +template +struct has_flip().flip())>> + : std::true_type {}; + +template struct is_bit_reference_like { + static constexpr const bool value = + std::is_convertible::value && + std::is_nothrow_assignable::value && has_flip::value; +}; + +#ifdef _LIBCPP_VERSION + +// Workaround for libc++ incompatibility with C++ standard. +// According to the Standard, `bitset::operator[] const` returns bool. +template +struct is_bit_reference_like> { + static constexpr const bool value = true; +}; + +#endif + +} // namespace detail + +// We can't use std::vector::reference and +// std::bitset::reference because the compiler can't deduce Allocator and N +// in partial specialization. +template +struct formatter::value>> + : formatter { + template + FMT_CONSTEXPR auto format(const BitRef& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v, ctx); + } +}; + +template +auto ptr(const std::unique_ptr& p) -> const void* { + return p.get(); +} +template auto ptr(const std::shared_ptr& p) -> const void* { + return p.get(); +} + +template +struct formatter, Char, + enable_if_t::value>> + : formatter { + template + auto format(const std::atomic& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.load(), ctx); + } +}; + +#ifdef __cpp_lib_atomic_flag_test +template +struct formatter : formatter { + template + auto format(const std::atomic_flag& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.test(), ctx); + } +}; +#endif // __cpp_lib_atomic_flag_test + +template struct formatter, Char> { + private: + detail::dynamic_format_specs specs_; + + template + FMT_CONSTEXPR auto do_format(const std::complex& c, + detail::dynamic_format_specs& specs, + FormatContext& ctx, OutputIt out) const + -> OutputIt { + if (c.real() != 0) { + *out++ = Char('('); + out = detail::write(out, c.real(), specs, ctx.locale()); + specs.set_sign(sign::plus); + out = detail::write(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + *out++ = Char(')'); + return out; + } + out = detail::write(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + return out; + } + + public: + FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin(); + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type_constant::value); + } + + template + auto format(const std::complex& c, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + if (specs.dynamic()) { + detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision, + specs.precision_ref, ctx); + } + + if (specs.width == 0) return do_format(c, specs, ctx, ctx.out()); + auto buf = basic_memory_buffer(); + + auto outer_specs = format_specs(); + outer_specs.width = specs.width; + outer_specs.copy_fill_from(specs); + outer_specs.set_align(specs.align()); + + specs.width = 0; + specs.set_fill({}); + specs.set_align(align::none); + + do_format(c, specs, ctx, basic_appender(buf)); + return detail::write(ctx.out(), + basic_string_view(buf.data(), buf.size()), + outer_specs); + } +}; + +template +struct formatter, Char, + enable_if_t, Char>::value>> + : formatter, Char> { + template + auto format(std::reference_wrapper ref, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter, Char>::format(ref.get(), ctx); + } +}; + +FMT_END_NAMESPACE +#endif // FMT_STD_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/bundled/xchar.h b/vendor/opensource/log_lib/spdlog/fmt/bundled/xchar.h new file mode 100755 index 0000000000000000000000000000000000000000..90994fff6e2e7a1bd3029ffc2aabea488d2088ff --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/bundled/xchar.h @@ -0,0 +1,369 @@ +// Formatting library for C++ - optional wchar_t and exotic character support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_XCHAR_H_ +#define FMT_XCHAR_H_ + +#include "color.h" +#include "format.h" +#include "ostream.h" +#include "ranges.h" + +#ifndef FMT_MODULE +# include +# if FMT_USE_LOCALE +# include +# endif +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +template +using is_exotic_char = bool_constant::value>; + +template struct format_string_char {}; + +template +struct format_string_char< + S, void_t())))>> { + using type = char_t; +}; + +template +struct format_string_char< + S, enable_if_t::value>> { + using type = typename S::char_type; +}; + +template +using format_string_char_t = typename format_string_char::type; + +inline auto write_loc(basic_appender out, loc_value value, + const format_specs& specs, locale_ref loc) -> bool { +#if FMT_USE_LOCALE + auto& numpunct = + std::use_facet>(loc.get()); + auto separator = std::wstring(); + auto grouping = numpunct.grouping(); + if (!grouping.empty()) separator = std::wstring(1, numpunct.thousands_sep()); + return value.visit(loc_writer{out, specs, separator, grouping, {}}); +#endif + return false; +} +} // namespace detail + +FMT_BEGIN_EXPORT + +using wstring_view = basic_string_view; +using wformat_parse_context = parse_context; +using wformat_context = buffered_context; +using wformat_args = basic_format_args; +using wmemory_buffer = basic_memory_buffer; + +template struct basic_fstring { + private: + basic_string_view str_; + + static constexpr int num_static_named_args = + detail::count_static_named_args(); + + using checker = detail::format_string_checker< + Char, static_cast(sizeof...(T)), num_static_named_args, + num_static_named_args != detail::count_named_args()>; + + using arg_pack = detail::arg_pack; + + public: + using t = basic_fstring; + + template >::value)> + FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_fstring(const S& s) : str_(s) { + if (FMT_USE_CONSTEVAL) + detail::parse_format_string(s, checker(s, arg_pack())); + } + template ::value&& + std::is_same::value)> + FMT_ALWAYS_INLINE basic_fstring(const S&) : str_(S()) { + FMT_CONSTEXPR auto sv = basic_string_view(S()); + FMT_CONSTEXPR int ignore = + (parse_format_string(sv, checker(sv, arg_pack())), 0); + detail::ignore_unused(ignore); + } + basic_fstring(runtime_format_string fmt) : str_(fmt.str) {} + + operator basic_string_view() const { return str_; } + auto get() const -> basic_string_view { return str_; } +}; + +template +using basic_format_string = basic_fstring; + +template +using wformat_string = typename basic_format_string::t; +inline auto runtime(wstring_view s) -> runtime_format_string { + return {{s}}; +} + +#ifdef __cpp_char8_t +template <> struct is_char : bool_constant {}; +#endif + +template +constexpr auto make_wformat_args(T&... args) + -> decltype(fmt::make_format_args(args...)) { + return fmt::make_format_args(args...); +} + +#if !FMT_USE_NONTYPE_TEMPLATE_ARGS +inline namespace literals { +inline auto operator""_a(const wchar_t* s, size_t) -> detail::udl_arg { + return {s}; +} +} // namespace literals +#endif + +template +auto join(It begin, Sentinel end, wstring_view sep) + -> join_view { + return {begin, end, sep}; +} + +template ::value)> +auto join(Range&& range, wstring_view sep) + -> join_view { + return join(std::begin(range), std::end(range), sep); +} + +template +auto join(std::initializer_list list, wstring_view sep) + -> join_view { + return join(std::begin(list), std::end(list), sep); +} + +template ::value)> +auto join(const Tuple& tuple, basic_string_view sep) + -> tuple_join_view { + return {tuple, sep}; +} + +template ::value)> +auto vformat(basic_string_view fmt, + typename detail::vformat_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vformat_to(buf, fmt, args); + return {buf.data(), buf.size()}; +} + +template +auto format(wformat_string fmt, T&&... args) -> std::wstring { + return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template +auto format_to(OutputIt out, wformat_string fmt, T&&... args) + -> OutputIt { + return vformat_to(out, fmt::wstring_view(fmt), + fmt::make_wformat_args(args...)); +} + +// Pass char_t as a default template parameter instead of using +// std::basic_string> to reduce the symbol size. +template , + FMT_ENABLE_IF(!std::is_same::value && + !std::is_same::value)> +auto format(const S& fmt, T&&... args) -> std::basic_string { + return vformat(detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat(const Locale& loc, const S& fmt, + typename detail::vformat_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vformat_to(buf, detail::to_string_view(fmt), args, + detail::locale_ref(loc)); + return {buf.data(), buf.size()}; +} + +template , + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto format(const Locale& loc, const S& fmt, T&&... args) + -> std::basic_string { + return vformat(loc, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_exotic_char::value)> +auto vformat_to(OutputIt out, const S& fmt, + typename detail::vformat_args::type args) -> OutputIt { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, detail::to_string_view(fmt), args); + return detail::get_iterator(buf, out); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value && + !std::is_same::value && + !std::is_same::value)> +inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt { + return vformat_to(out, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat_to(OutputIt out, const Locale& loc, const S& fmt, + typename detail::vformat_args::type args) + -> OutputIt { + auto&& buf = detail::get_buffer(out); + vformat_to(buf, detail::to_string_view(fmt), args, detail::locale_ref(loc)); + return detail::get_iterator(buf, out); +} + +template , + bool enable = detail::is_output_iterator::value && + detail::is_locale::value && + detail::is_exotic_char::value> +inline auto format_to(OutputIt out, const Locale& loc, const S& fmt, + T&&... args) -> + typename std::enable_if::type { + return vformat_to(out, loc, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template ::value&& + detail::is_exotic_char::value)> +inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view fmt, + typename detail::vformat_args::type args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + detail::vformat_to(buf, fmt, args); + return {buf.out(), buf.count()}; +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_exotic_char::value)> +inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args) + -> format_to_n_result { + return vformat_to_n(out, n, fmt::basic_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_exotic_char::value)> +inline auto formatted_size(const S& fmt, T&&... args) -> size_t { + auto buf = detail::counting_buffer(); + detail::vformat_to(buf, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); + return buf.count(); +} + +inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) { + auto buf = wmemory_buffer(); + detail::vformat_to(buf, fmt, args); + buf.push_back(L'\0'); + if (std::fputws(buf.data(), f) == -1) + FMT_THROW(system_error(errno, FMT_STRING("cannot write to file"))); +} + +inline void vprint(wstring_view fmt, wformat_args args) { + vprint(stdout, fmt, args); +} + +template +void print(std::FILE* f, wformat_string fmt, T&&... args) { + return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template void print(wformat_string fmt, T&&... args) { + return vprint(wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template +void println(std::FILE* f, wformat_string fmt, T&&... args) { + return print(f, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +template void println(wformat_string fmt, T&&... args) { + return print(L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +inline auto vformat(text_style ts, wstring_view fmt, wformat_args args) + -> std::wstring { + auto buf = wmemory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + return {buf.data(), buf.size()}; +} + +template +inline auto format(text_style ts, wformat_string fmt, T&&... args) + -> std::wstring { + return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...)); +} + +template +FMT_DEPRECATED void print(std::FILE* f, text_style ts, wformat_string fmt, + const T&... args) { + vprint(f, ts, fmt, fmt::make_wformat_args(args...)); +} + +template +FMT_DEPRECATED void print(text_style ts, wformat_string fmt, + const T&... args) { + return print(stdout, ts, fmt, args...); +} + +inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) { + auto buffer = basic_memory_buffer(); + detail::vformat_to(buffer, fmt, args); + detail::write_buffer(os, buffer); +} + +template +void print(std::wostream& os, wformat_string fmt, T&&... args) { + vprint(os, fmt, fmt::make_format_args>(args...)); +} + +template +void println(std::wostream& os, wformat_string fmt, T&&... args) { + print(os, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +/// Converts `value` to `std::wstring` using the default format for type `T`. +template inline auto to_wstring(const T& value) -> std::wstring { + return format(FMT_STRING(L"{}"), value); +} +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_XCHAR_H_ diff --git a/vendor/opensource/log_lib/spdlog/fmt/chrono.h b/vendor/opensource/log_lib/spdlog/fmt/chrono.h new file mode 100755 index 0000000000000000000000000000000000000000..a72a5bd64100c1fd73e345455263ec7d45e3a041 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/chrono.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's chrono support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/compile.h b/vendor/opensource/log_lib/spdlog/fmt/compile.h new file mode 100755 index 0000000000000000000000000000000000000000..3c9c25d8b192812acdb30f78d47fc6419b22847c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/compile.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's compile-time support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/fmt.h b/vendor/opensource/log_lib/spdlog/fmt/fmt.h new file mode 100755 index 0000000000000000000000000000000000000000..81159e3c1742a4594b813e828b2c46ce98da5c5f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/fmt.h @@ -0,0 +1,30 @@ +// +// Copyright(c) 2016-2018 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// +// Include a bundled header-only copy of fmtlib or an external one. +// By default spdlog include its own copy. +// +#include + +#if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format + #include +#elif !defined(SPDLOG_FMT_EXTERNAL) + #if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY) + #define FMT_HEADER_ONLY + #endif + #ifndef FMT_USE_WINDOWS_H + #define FMT_USE_WINDOWS_H 0 + #endif + + #include + #include + +#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib + #include + #include +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/ostr.h b/vendor/opensource/log_lib/spdlog/fmt/ostr.h new file mode 100755 index 0000000000000000000000000000000000000000..2b901055f3c0f7b3e8b538c5425f41ad71220de1 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/ostr.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's ostream support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/ranges.h b/vendor/opensource/log_lib/spdlog/fmt/ranges.h new file mode 100755 index 0000000000000000000000000000000000000000..5bb91e9acb7fdf679cb2231a401ae86792f1a0a0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/ranges.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's ranges support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/std.h b/vendor/opensource/log_lib/spdlog/fmt/std.h new file mode 100755 index 0000000000000000000000000000000000000000..dabe6f69d8b94169f70456652c3f4a4dc79cb46c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/std.h @@ -0,0 +1,24 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's std support (for formatting e.g. +// std::filesystem::path, std::thread::id, std::monostate, std::variant, ...) +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/fmt/xchar.h b/vendor/opensource/log_lib/spdlog/fmt/xchar.h new file mode 100755 index 0000000000000000000000000000000000000000..2525f058648d7a7bf65f5218efb747caa20a2ee4 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fmt/xchar.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's xchar support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/vendor/opensource/log_lib/spdlog/formatter.h b/vendor/opensource/log_lib/spdlog/formatter.h new file mode 100755 index 0000000000000000000000000000000000000000..4d482f827e671c7acec2b4aaa9fa2dd0bc8f2dbb --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/formatter.h @@ -0,0 +1,17 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { + +class formatter { +public: + virtual ~formatter() = default; + virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; + virtual std::unique_ptr clone() const = 0; +}; +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/fwd.h b/vendor/opensource/log_lib/spdlog/fwd.h new file mode 100755 index 0000000000000000000000000000000000000000..647b16bf0fa41f9f5806f38b94eaa136d4d6befc --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/fwd.h @@ -0,0 +1,18 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +namespace spdlog { +class logger; +class formatter; + +namespace sinks { +class sink; +} + +namespace level { +enum level_enum : int; +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/logger-inl.h b/vendor/opensource/log_lib/spdlog/logger-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..5218fe4c440d48ed0191aa691f094d3afd8ce3bf --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/logger-inl.h @@ -0,0 +1,198 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#include + +namespace spdlog { + +// public methods +SPDLOG_INLINE logger::logger(const logger &other) + : name_(other.name_), + sinks_(other.sinks_), + level_(other.level_.load(std::memory_order_relaxed)), + flush_level_(other.flush_level_.load(std::memory_order_relaxed)), + custom_err_handler_(other.custom_err_handler_), + tracer_(other.tracer_) {} + +SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT + : name_(std::move(other.name_)), + sinks_(std::move(other.sinks_)), + level_(other.level_.load(std::memory_order_relaxed)), + flush_level_(other.flush_level_.load(std::memory_order_relaxed)), + custom_err_handler_(std::move(other.custom_err_handler_)), + tracer_(std::move(other.tracer_)) + +{} + +SPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT { + this->swap(other); + return *this; +} + +SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT { + name_.swap(other.name_); + sinks_.swap(other.sinks_); + + // swap level_ + auto other_level = other.level_.load(); + auto my_level = level_.exchange(other_level); + other.level_.store(my_level); + + // swap flush level_ + other_level = other.flush_level_.load(); + my_level = flush_level_.exchange(other_level); + other.flush_level_.store(my_level); + + custom_err_handler_.swap(other.custom_err_handler_); + std::swap(tracer_, other.tracer_); +} + +SPDLOG_INLINE void swap(logger &a, logger &b) { a.swap(b); } + +SPDLOG_INLINE void logger::set_level(level::level_enum log_level) { level_.store(log_level); } + +SPDLOG_INLINE level::level_enum logger::level() const { + return static_cast(level_.load(std::memory_order_relaxed)); +} + +SPDLOG_INLINE const std::string &logger::name() const { return name_; } + +// set formatting for the sinks in this logger. +// each sink will get a separate instance of the formatter object. +SPDLOG_INLINE void logger::set_formatter(std::unique_ptr f) { + for (auto it = sinks_.begin(); it != sinks_.end(); ++it) { + if (std::next(it) == sinks_.end()) { + // last element - we can be move it. + (*it)->set_formatter(std::move(f)); + break; // to prevent clang-tidy warning + } else { + (*it)->set_formatter(f->clone()); + } + } +} + +SPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type time_type) { + auto new_formatter = details::make_unique(std::move(pattern), time_type); + set_formatter(std::move(new_formatter)); +} + +// create new backtrace sink and move to it all our child sinks +SPDLOG_INLINE void logger::enable_backtrace(size_t n_messages) { tracer_.enable(n_messages); } + +// restore orig sinks and level and delete the backtrace sink +SPDLOG_INLINE void logger::disable_backtrace() { tracer_.disable(); } + +SPDLOG_INLINE void logger::dump_backtrace() { dump_backtrace_(); } + +// flush functions +SPDLOG_INLINE void logger::flush() { flush_(); } + +SPDLOG_INLINE void logger::flush_on(level::level_enum log_level) { flush_level_.store(log_level); } + +SPDLOG_INLINE level::level_enum logger::flush_level() const { + return static_cast(flush_level_.load(std::memory_order_relaxed)); +} + +// sinks +SPDLOG_INLINE const std::vector &logger::sinks() const { return sinks_; } + +SPDLOG_INLINE std::vector &logger::sinks() { return sinks_; } + +// error handler +SPDLOG_INLINE void logger::set_error_handler(err_handler handler) { + custom_err_handler_ = std::move(handler); +} + +// create new logger with same sinks and configuration. +SPDLOG_INLINE std::shared_ptr logger::clone(std::string logger_name) { + auto cloned = std::make_shared(*this); + cloned->name_ = std::move(logger_name); + return cloned; +} + +// protected methods +SPDLOG_INLINE void logger::log_it_(const spdlog::details::log_msg &log_msg, + bool log_enabled, + bool traceback_enabled) { + if (log_enabled) { + sink_it_(log_msg); + } + if (traceback_enabled) { + tracer_.push_back(log_msg); + } +} + +SPDLOG_INLINE void logger::sink_it_(const details::log_msg &msg) { + for (auto &sink : sinks_) { + if (sink->should_log(msg.level)) { + SPDLOG_TRY { sink->log(msg); } + SPDLOG_LOGGER_CATCH(msg.source) + } + } + + if (should_flush_(msg)) { + flush_(); + } +} + +SPDLOG_INLINE void logger::flush_() { + for (auto &sink : sinks_) { + SPDLOG_TRY { sink->flush(); } + SPDLOG_LOGGER_CATCH(source_loc()) + } +} + +SPDLOG_INLINE void logger::dump_backtrace_() { + using details::log_msg; + if (tracer_.enabled() && !tracer_.empty()) { + sink_it_( + log_msg{name(), level::info, "****************** Backtrace Start ******************"}); + tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); }); + sink_it_( + log_msg{name(), level::info, "****************** Backtrace End ********************"}); + } +} + +SPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg) { + auto flush_level = flush_level_.load(std::memory_order_relaxed); + return (msg.level >= flush_level) && (msg.level != level::off); +} + +SPDLOG_INLINE void logger::err_handler_(const std::string &msg) { + if (custom_err_handler_) { + custom_err_handler_(msg); + } else { + using std::chrono::system_clock; + static std::mutex mutex; + static std::chrono::system_clock::time_point last_report_time; + static size_t err_counter = 0; + std::lock_guard lk{mutex}; + auto now = system_clock::now(); + err_counter++; + if (now - last_report_time < std::chrono::seconds(1)) { + return; + } + last_report_time = now; + auto tm_time = details::os::localtime(system_clock::to_time_t(now)); + char date_buf[64]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); +#if defined(USING_R) && defined(R_R_H) // if in R environment + REprintf("[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, name().c_str(), + msg.c_str()); +#else + std::fprintf(stderr, "[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, + name().c_str(), msg.c_str()); +#endif + } +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/logger.h b/vendor/opensource/log_lib/spdlog/logger.h new file mode 100755 index 0000000000000000000000000000000000000000..f49bdc009a3e1dc8ccd021d98925406332f08ea5 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/logger.h @@ -0,0 +1,379 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Thread safe logger (except for set_error_handler()) +// Has name, log level, vector of std::shared sink pointers and formatter +// Upon each log write the logger: +// 1. Checks if its log level is enough to log the message and if yes: +// 2. Call the underlying sinks to do the job. +// 3. Each sink use its own private copy of a formatter to format the message +// and send to its destination. +// +// The use of private formatter per sink provides the opportunity to cache some +// formatted data, and support for different format per sink. + +#include +#include +#include + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + #ifndef _WIN32 + #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows + #endif + #include +#endif + +#include + +#ifndef SPDLOG_NO_EXCEPTIONS + #define SPDLOG_LOGGER_CATCH(location) \ + catch (const std::exception &ex) { \ + if (location.filename) { \ + err_handler_(fmt_lib::format(SPDLOG_FMT_STRING("{} [{}({})]"), ex.what(), \ + location.filename, location.line)); \ + } else { \ + err_handler_(ex.what()); \ + } \ + } \ + catch (...) { \ + err_handler_("Rethrowing unknown exception in logger"); \ + throw; \ + } +#else + #define SPDLOG_LOGGER_CATCH(location) +#endif + +namespace spdlog { + +class SPDLOG_API logger { +public: + // Empty logger + explicit logger(std::string name) + : name_(std::move(name)), + sinks_() {} + + // Logger with range on sinks + template + logger(std::string name, It begin, It end) + : name_(std::move(name)), + sinks_(begin, end) {} + + // Logger with single sink + logger(std::string name, sink_ptr single_sink) + : logger(std::move(name), {std::move(single_sink)}) {} + + // Logger with sinks init list + logger(std::string name, sinks_init_list sinks) + : logger(std::move(name), sinks.begin(), sinks.end()) {} + + virtual ~logger() = default; + + logger(const logger &other); + logger(logger &&other) SPDLOG_NOEXCEPT; + logger &operator=(logger other) SPDLOG_NOEXCEPT; + void swap(spdlog::logger &other) SPDLOG_NOEXCEPT; + + template + void log(source_loc loc, level::level_enum lvl, format_string_t fmt, Args &&...args) { + log_(loc, lvl, details::to_string_view(fmt), std::forward(args)...); + } + + template + void log(level::level_enum lvl, format_string_t fmt, Args &&...args) { + log(source_loc{}, lvl, fmt, std::forward(args)...); + } + + template + void log(level::level_enum lvl, const T &msg) { + log(source_loc{}, lvl, msg); + } + + // T cannot be statically converted to format string (including string_view/wstring_view) + template ::value, + int>::type = 0> + void log(source_loc loc, level::level_enum lvl, const T &msg) { + log(loc, lvl, "{}", msg); + } + + void log(log_clock::time_point log_time, + source_loc loc, + level::level_enum lvl, + string_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + details::log_msg log_msg(log_time, loc, name_, lvl, msg); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(source_loc loc, level::level_enum lvl, string_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + details::log_msg log_msg(loc, name_, lvl, msg); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(level::level_enum lvl, string_view_t msg) { log(source_loc{}, lvl, msg); } + + template + void trace(format_string_t fmt, Args &&...args) { + log(level::trace, fmt, std::forward(args)...); + } + + template + void debug(format_string_t fmt, Args &&...args) { + log(level::debug, fmt, std::forward(args)...); + } + + template + void info(format_string_t fmt, Args &&...args) { + log(level::info, fmt, std::forward(args)...); + } + + template + void warn(format_string_t fmt, Args &&...args) { + log(level::warn, fmt, std::forward(args)...); + } + + template + void error(format_string_t fmt, Args &&...args) { + log(level::err, fmt, std::forward(args)...); + } + + template + void critical(format_string_t fmt, Args &&...args) { + log(level::critical, fmt, std::forward(args)...); + } + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + template + void log(source_loc loc, level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + log_(loc, lvl, details::to_string_view(fmt), std::forward(args)...); + } + + template + void log(level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + log(source_loc{}, lvl, fmt, std::forward(args)...); + } + + void log(log_clock::time_point log_time, + source_loc loc, + level::level_enum lvl, + wstring_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(log_time, loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(source_loc loc, level::level_enum lvl, wstring_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(level::level_enum lvl, wstring_view_t msg) { log(source_loc{}, lvl, msg); } + + template + void trace(wformat_string_t fmt, Args &&...args) { + log(level::trace, fmt, std::forward(args)...); + } + + template + void debug(wformat_string_t fmt, Args &&...args) { + log(level::debug, fmt, std::forward(args)...); + } + + template + void info(wformat_string_t fmt, Args &&...args) { + log(level::info, fmt, std::forward(args)...); + } + + template + void warn(wformat_string_t fmt, Args &&...args) { + log(level::warn, fmt, std::forward(args)...); + } + + template + void error(wformat_string_t fmt, Args &&...args) { + log(level::err, fmt, std::forward(args)...); + } + + template + void critical(wformat_string_t fmt, Args &&...args) { + log(level::critical, fmt, std::forward(args)...); + } +#endif + + template + void trace(const T &msg) { + log(level::trace, msg); + } + + template + void debug(const T &msg) { + log(level::debug, msg); + } + + template + void info(const T &msg) { + log(level::info, msg); + } + + template + void warn(const T &msg) { + log(level::warn, msg); + } + + template + void error(const T &msg) { + log(level::err, msg); + } + + template + void critical(const T &msg) { + log(level::critical, msg); + } + + // return true logging is enabled for the given level. + bool should_log(level::level_enum msg_level) const { + return msg_level >= level_.load(std::memory_order_relaxed); + } + + // return true if backtrace logging is enabled. + bool should_backtrace() const { return tracer_.enabled(); } + + void set_level(level::level_enum log_level); + + level::level_enum level() const; + + const std::string &name() const; + + // set formatting for the sinks in this logger. + // each sink will get a separate instance of the formatter object. + void set_formatter(std::unique_ptr f); + + // set formatting for the sinks in this logger. + // equivalent to + // set_formatter(make_unique(pattern, time_type)) + // Note: each sink will get a new instance of a formatter object, replacing the old one. + void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); + + // backtrace support. + // efficiently store all debug/trace messages in a circular buffer until needed for debugging. + void enable_backtrace(size_t n_messages); + void disable_backtrace(); + void dump_backtrace(); + + // flush functions + void flush(); + void flush_on(level::level_enum log_level); + level::level_enum flush_level() const; + + // sinks + const std::vector &sinks() const; + + std::vector &sinks(); + + // error handler + void set_error_handler(err_handler); + + // create new logger with same sinks and configuration. + virtual std::shared_ptr clone(std::string logger_name); + +protected: + std::string name_; + std::vector sinks_; + spdlog::level_t level_{level::info}; + spdlog::level_t flush_level_{level::off}; + err_handler custom_err_handler_{nullptr}; + details::backtracer tracer_; + + // common implementation for after templated public api has been resolved + template + void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&...args) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + SPDLOG_TRY { + memory_buf_t buf; +#ifdef SPDLOG_USE_STD_FORMAT + fmt_lib::vformat_to(std::back_inserter(buf), fmt, fmt_lib::make_format_args(args...)); +#else + fmt::vformat_to(fmt::appender(buf), fmt, fmt::make_format_args(args...)); +#endif + + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + SPDLOG_LOGGER_CATCH(loc) + } + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + template + void log_(source_loc loc, level::level_enum lvl, wstring_view_t fmt, Args &&...args) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + SPDLOG_TRY { + // format to wmemory_buffer and convert to utf8 + wmemory_buf_t wbuf; + fmt_lib::vformat_to(std::back_inserter(wbuf), fmt, + fmt_lib::make_format_args(args...)); + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + SPDLOG_LOGGER_CATCH(loc) + } +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + + // log the given message (if the given log level is high enough), + // and save backtrace (if backtrace is enabled). + void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled); + virtual void sink_it_(const details::log_msg &msg); + virtual void flush_(); + void dump_backtrace_(); + bool should_flush_(const details::log_msg &msg); + + // handle errors during logging. + // default handler prints the error to stderr at max rate of 1 message/sec. + void err_handler_(const std::string &msg); +}; + +void swap(logger &a, logger &b); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "logger-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/mdc.h b/vendor/opensource/log_lib/spdlog/mdc.h new file mode 100755 index 0000000000000000000000000000000000000000..e428f4f77ed6da663574859bf5a839fe6c408eda --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/mdc.h @@ -0,0 +1,52 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#if defined(SPDLOG_NO_TLS) + #error "This header requires thread local storage support, but SPDLOG_NO_TLS is defined." +#endif + +#include +#include + +#include + +// MDC is a double_online map of key->string values stored in thread local storage whose content will be +// printed by the loggers. Note: Not supported in async mode (thread local storage - so the async +// thread pool have different copy). +// +// Usage example: +// spdlog::mdc::put("mdc_key_1", "mdc_value_1"); +// spdlog::info("Hello, {}", "World!"); // => [2024-04-26 02:08:05.040] [info] +// [mdc_key_1:mdc_value_1] Hello, World! + +namespace spdlog { +class SPDLOG_API mdc { +public: + using mdc_map_t = std::map; + + static void put(const std::string &key, const std::string &value) { + get_context()[key] = value; + } + + static std::string get(const std::string &key) { + auto &context = get_context(); + auto it = context.find(key); + if (it != context.end()) { + return it->second; + } + return ""; + } + + static void remove(const std::string &key) { get_context().erase(key); } + + static void clear() { get_context().clear(); } + + static mdc_map_t &get_context() { + static thread_local mdc_map_t context; + return context; + } +}; + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/pattern_formatter-inl.h b/vendor/opensource/log_lib/spdlog/pattern_formatter-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..fd408ed527a980a040caa350c6056547a1fad1e2 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/pattern_formatter-inl.h @@ -0,0 +1,1340 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#ifndef SPDLOG_NO_TLS + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +/////////////////////////////////////////////////////////////////////// +// name & level pattern appender +/////////////////////////////////////////////////////////////////////// + +class scoped_padder { +public: + scoped_padder(size_t wrapped_size, const padding_info &padinfo, memory_buf_t &dest) + : padinfo_(padinfo), + dest_(dest) { + remaining_pad_ = static_cast(padinfo.width_) - static_cast(wrapped_size); + if (remaining_pad_ <= 0) { + return; + } + + if (padinfo_.side_ == padding_info::pad_side::left) { + pad_it(remaining_pad_); + remaining_pad_ = 0; + } else if (padinfo_.side_ == padding_info::pad_side::center) { + auto half_pad = remaining_pad_ / 2; + auto reminder = remaining_pad_ & 1; + pad_it(half_pad); + remaining_pad_ = half_pad + reminder; // for the right side + } + } + + template + static unsigned int count_digits(T n) { + return fmt_helper::count_digits(n); + } + + ~scoped_padder() { + if (remaining_pad_ >= 0) { + pad_it(remaining_pad_); + } else if (padinfo_.truncate_) { + long new_size = static_cast(dest_.size()) + remaining_pad_; + if (new_size < 0) { + new_size = 0; + } + dest_.resize(static_cast(new_size)); + } + } + +private: + void pad_it(long count) { + fmt_helper::append_string_view(string_view_t(spaces_.data(), static_cast(count)), + dest_); + } + + const padding_info &padinfo_; + memory_buf_t &dest_; + long remaining_pad_; + string_view_t spaces_{" ", 64}; +}; + +struct null_scoped_padder { + null_scoped_padder(size_t /*wrapped_size*/, + const padding_info & /*padinfo*/, + memory_buf_t & /*dest*/) {} + + template + static unsigned int count_digits(T /* number */) { + return 0; + } +}; + +template +class name_formatter final : public flag_formatter { +public: + explicit name_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + ScopedPadder p(msg.logger_name.size(), padinfo_, dest); + fmt_helper::append_string_view(msg.logger_name, dest); + } +}; + +// log level appender +template +class level_formatter final : public flag_formatter { +public: + explicit level_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const string_view_t &level_name = level::to_string_view(msg.level); + ScopedPadder p(level_name.size(), padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); + } +}; + +// short log level appender +template +class short_level_formatter final : public flag_formatter { +public: + explicit short_level_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + string_view_t level_name{level::to_short_c_str(msg.level)}; + ScopedPadder p(level_name.size(), padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); + } +}; + +/////////////////////////////////////////////////////////////////////// +// Date time pattern appenders +/////////////////////////////////////////////////////////////////////// + +static const char *ampm(const tm &t) { return t.tm_hour >= 12 ? "PM" : "AM"; } + +static int to12h(const tm &t) { return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour; } + +// Abbreviated weekday name +static std::array days{{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}}; + +template +class a_formatter final : public flag_formatter { +public: + explicit a_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{days[static_cast(tm_time.tm_wday)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Full weekday name +static std::array full_days{ + {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}}; + +template +class A_formatter : public flag_formatter { +public: + explicit A_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{full_days[static_cast(tm_time.tm_wday)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Abbreviated month +static const std::array months{ + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}}; + +template +class b_formatter final : public flag_formatter { +public: + explicit b_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{months[static_cast(tm_time.tm_mon)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Full month name +static const std::array full_months{{"January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December"}}; + +template +class B_formatter final : public flag_formatter { +public: + explicit B_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{full_months[static_cast(tm_time.tm_mon)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Date and time representation (Thu Aug 23 15:35:46 2014) +template +class c_formatter final : public flag_formatter { +public: + explicit c_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 24; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::append_string_view(days[static_cast(tm_time.tm_wday)], dest); + dest.push_back(' '); + fmt_helper::append_string_view(months[static_cast(tm_time.tm_mon)], dest); + dest.push_back(' '); + fmt_helper::append_int(tm_time.tm_mday, dest); + dest.push_back(' '); + // time + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + dest.push_back(' '); + fmt_helper::append_int(tm_time.tm_year + 1900, dest); + } +}; + +// year - 2 digit +template +class C_formatter final : public flag_formatter { +public: + explicit C_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_year % 100, dest); + } +}; + +// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 +template +class D_formatter final : public flag_formatter { +public: + explicit D_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 8; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_mon + 1, dest); + dest.push_back('/'); + fmt_helper::pad2(tm_time.tm_mday, dest); + dest.push_back('/'); + fmt_helper::pad2(tm_time.tm_year % 100, dest); + } +}; + +// year - 4 digit +template +class Y_formatter final : public flag_formatter { +public: + explicit Y_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 4; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(tm_time.tm_year + 1900, dest); + } +}; + +// month 1-12 +template +class m_formatter final : public flag_formatter { +public: + explicit m_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_mon + 1, dest); + } +}; + +// day of month 1-31 +template +class d_formatter final : public flag_formatter { +public: + explicit d_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_mday, dest); + } +}; + +// hours in 24 format 0-23 +template +class H_formatter final : public flag_formatter { +public: + explicit H_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_hour, dest); + } +}; + +// hours in 12 format 1-12 +template +class I_formatter final : public flag_formatter { +public: + explicit I_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(to12h(tm_time), dest); + } +}; + +// minutes 0-59 +template +class M_formatter final : public flag_formatter { +public: + explicit M_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_min, dest); + } +}; + +// seconds 0-59 +template +class S_formatter final : public flag_formatter { +public: + explicit S_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_sec, dest); + } +}; + +// milliseconds +template +class e_formatter final : public flag_formatter { +public: + explicit e_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto millis = fmt_helper::time_fraction(msg.time); + const size_t field_size = 3; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad3(static_cast(millis.count()), dest); + } +}; + +// microseconds +template +class f_formatter final : public flag_formatter { +public: + explicit f_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto micros = fmt_helper::time_fraction(msg.time); + + const size_t field_size = 6; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad6(static_cast(micros.count()), dest); + } +}; + +// nanoseconds +template +class F_formatter final : public flag_formatter { +public: + explicit F_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto ns = fmt_helper::time_fraction(msg.time); + const size_t field_size = 9; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad9(static_cast(ns.count()), dest); + } +}; + +// seconds since epoch +template +class E_formatter final : public flag_formatter { +public: + explicit E_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const size_t field_size = 10; + ScopedPadder p(field_size, padinfo_, dest); + auto duration = msg.time.time_since_epoch(); + auto seconds = std::chrono::duration_cast(duration).count(); + fmt_helper::append_int(seconds, dest); + } +}; + +// AM/PM +template +class p_formatter final : public flag_formatter { +public: + explicit p_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_string_view(ampm(tm_time), dest); + } +}; + +// 12 hour clock 02:55:02 pm +template +class r_formatter final : public flag_formatter { +public: + explicit r_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 11; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(to12h(tm_time), dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + dest.push_back(' '); + fmt_helper::append_string_view(ampm(tm_time), dest); + } +}; + +// 24-hour HH:MM time, equivalent to %H:%M +template +class R_formatter final : public flag_formatter { +public: + explicit R_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 5; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + } +}; + +// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S +template +class T_formatter final : public flag_formatter { +public: + explicit T_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 8; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + } +}; + +// ISO 8601 offset from UTC in timezone (+-HH:MM) +template +class z_formatter final : public flag_formatter { +public: + explicit z_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + z_formatter() = default; + z_formatter(const z_formatter &) = delete; + z_formatter &operator=(const z_formatter &) = delete; + + void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 6; + ScopedPadder p(field_size, padinfo_, dest); + + auto total_minutes = get_cached_offset(msg, tm_time); + bool is_negative = total_minutes < 0; + if (is_negative) { + total_minutes = -total_minutes; + dest.push_back('-'); + } else { + dest.push_back('+'); + } + + fmt_helper::pad2(total_minutes / 60, dest); // hours + dest.push_back(':'); + fmt_helper::pad2(total_minutes % 60, dest); // minutes + } + +private: + log_clock::time_point last_update_{std::chrono::seconds(0)}; + int offset_minutes_{0}; + + int get_cached_offset(const log_msg &msg, const std::tm &tm_time) { + // refresh every 10 seconds + if (msg.time - last_update_ >= std::chrono::seconds(10)) { + offset_minutes_ = os::utc_minutes_offset(tm_time); + last_update_ = msg.time; + } + return offset_minutes_; + } +}; + +// Thread id +template +class t_formatter final : public flag_formatter { +public: + explicit t_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const auto field_size = ScopedPadder::count_digits(msg.thread_id); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(msg.thread_id, dest); + } +}; + +// Current pid +template +class pid_formatter final : public flag_formatter { +public: + explicit pid_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + const auto pid = static_cast(details::os::pid()); + auto field_size = ScopedPadder::count_digits(pid); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(pid, dest); + } +}; + +template +class v_formatter final : public flag_formatter { +public: + explicit v_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + ScopedPadder p(msg.payload.size(), padinfo_, dest); + fmt_helper::append_string_view(msg.payload, dest); + } +}; + +class ch_formatter final : public flag_formatter { +public: + explicit ch_formatter(char ch) + : ch_(ch) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + dest.push_back(ch_); + } + +private: + char ch_; +}; + +// aggregate user chars to display as is +class aggregate_formatter final : public flag_formatter { +public: + aggregate_formatter() = default; + + void add_ch(char ch) { str_ += ch; } + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + fmt_helper::append_string_view(str_, dest); + } + +private: + std::string str_; +}; + +// mark the color range. expect it to be in the form of "%^colored text%$" +class color_start_formatter final : public flag_formatter { +public: + explicit color_start_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + msg.color_range_start = dest.size(); + } +}; + +class color_stop_formatter final : public flag_formatter { +public: + explicit color_stop_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + msg.color_range_end = dest.size(); + } +}; + +// print source location +template +class source_location_formatter final : public flag_formatter { +public: + explicit source_location_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + + size_t text_size; + if (padinfo_.enabled()) { + // calc text size for padding based on "filename:line" + text_size = std::char_traits::length(msg.source.filename) + + ScopedPadder::count_digits(msg.source.line) + 1; + } else { + text_size = 0; + } + + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.filename, dest); + dest.push_back(':'); + fmt_helper::append_int(msg.source.line, dest); + } +}; + +// print source filename +template +class source_filename_formatter final : public flag_formatter { +public: + explicit source_filename_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + size_t text_size = + padinfo_.enabled() ? std::char_traits::length(msg.source.filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.filename, dest); + } +}; + +template +class short_filename_formatter final : public flag_formatter { +public: + explicit short_filename_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4127) // consider using 'if constexpr' instead +#endif // _MSC_VER + static const char *basename(const char *filename) { + // if the size is 2 (1 character + null terminator) we can use the more efficient strrchr + // the branch will be elided by optimizations + if (sizeof(os::folder_seps) == 2) { + const char *rv = std::strrchr(filename, os::folder_seps[0]); + return rv != nullptr ? rv + 1 : filename; + } else { + const std::reverse_iterator begin(filename + std::strlen(filename)); + const std::reverse_iterator end(filename); + + const auto it = std::find_first_of(begin, end, std::begin(os::folder_seps), + std::end(os::folder_seps) - 1); + return it != end ? it.base() : filename; + } + } +#ifdef _MSC_VER + #pragma warning(pop) +#endif // _MSC_VER + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + auto filename = basename(msg.source.filename); + size_t text_size = padinfo_.enabled() ? std::char_traits::length(filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(filename, dest); + } +}; + +template +class source_linenum_formatter final : public flag_formatter { +public: + explicit source_linenum_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + + auto field_size = ScopedPadder::count_digits(msg.source.line); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(msg.source.line, dest); + } +}; + +// print source funcname +template +class source_funcname_formatter final : public flag_formatter { +public: + explicit source_funcname_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + size_t text_size = + padinfo_.enabled() ? std::char_traits::length(msg.source.funcname) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.funcname, dest); + } +}; + +// print elapsed time since last message +template +class elapsed_formatter final : public flag_formatter { +public: + using DurationUnits = Units; + + explicit elapsed_formatter(padding_info padinfo) + : flag_formatter(padinfo), + last_message_time_(log_clock::now()) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto delta = (std::max)(msg.time - last_message_time_, log_clock::duration::zero()); + auto delta_units = std::chrono::duration_cast(delta); + last_message_time_ = msg.time; + auto delta_count = static_cast(delta_units.count()); + auto n_digits = static_cast(ScopedPadder::count_digits(delta_count)); + ScopedPadder p(n_digits, padinfo_, dest); + fmt_helper::append_int(delta_count, dest); + } + +private: + log_clock::time_point last_message_time_; +}; + +// Class for formatting Mapped Diagnostic Context (MDC) in log messages. +// Example: [logger-name] [info] [mdc_key_1:mdc_value_1 mdc_key_2:mdc_value_2] some message +#ifndef SPDLOG_NO_TLS +template +class mdc_formatter : public flag_formatter { +public: + explicit mdc_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + auto &mdc_map = mdc::get_context(); + if (mdc_map.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } else { + format_mdc(mdc_map, dest); + } + } + + void format_mdc(const mdc::mdc_map_t &mdc_map, memory_buf_t &dest) { + auto last_element = --mdc_map.end(); + for (auto it = mdc_map.begin(); it != mdc_map.end(); ++it) { + auto &pair = *it; + const auto &key = pair.first; + const auto &value = pair.second; + size_t content_size = key.size() + value.size() + 1; // 1 for ':' + + if (it != last_element) { + content_size++; // 1 for ' ' + } + + ScopedPadder p(content_size, padinfo_, dest); + fmt_helper::append_string_view(key, dest); + fmt_helper::append_string_view(":", dest); + fmt_helper::append_string_view(value, dest); + if (it != last_element) { + fmt_helper::append_string_view(" ", dest); + } + } + } +}; +#endif + +// Full info formatter +// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%s:%#] %v +class full_formatter final : public flag_formatter { +public: + explicit full_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + + // cache the date/time part for the next second. + auto duration = msg.time.time_since_epoch(); + auto secs = duration_cast(duration); + + if (cache_timestamp_ != secs || cached_datetime_.size() == 0) { + cached_datetime_.clear(); + cached_datetime_.push_back('['); + fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_); + cached_datetime_.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_); + cached_datetime_.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mday, cached_datetime_); + cached_datetime_.push_back(' '); + + fmt_helper::pad2(tm_time.tm_hour, cached_datetime_); + cached_datetime_.push_back(':'); + + fmt_helper::pad2(tm_time.tm_min, cached_datetime_); + cached_datetime_.push_back(':'); + + fmt_helper::pad2(tm_time.tm_sec, cached_datetime_); + cached_datetime_.push_back('.'); + + cache_timestamp_ = secs; + } + dest.append(cached_datetime_.begin(), cached_datetime_.end()); + + auto millis = fmt_helper::time_fraction(msg.time); + fmt_helper::pad3(static_cast(millis.count()), dest); + dest.push_back(']'); + dest.push_back(' '); + + // append logger name if exists + if (msg.logger_name.size() > 0) { + dest.push_back('['); + fmt_helper::append_string_view(msg.logger_name, dest); + dest.push_back(']'); + dest.push_back(' '); + } + + dest.push_back('['); + // wrap the level name with color + msg.color_range_start = dest.size(); + // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + fmt_helper::append_string_view(level::to_string_view(msg.level), dest); + msg.color_range_end = dest.size(); + dest.push_back(']'); + dest.push_back(' '); + + // add source location if present + if (!msg.source.empty()) { + dest.push_back('['); + const char *filename = + details::short_filename_formatter::basename( + msg.source.filename); + fmt_helper::append_string_view(filename, dest); + dest.push_back(':'); + fmt_helper::append_int(msg.source.line, dest); + dest.push_back(']'); + dest.push_back(' '); + } + +#ifndef SPDLOG_NO_TLS + // add mdc if present + auto &mdc_map = mdc::get_context(); + if (!mdc_map.empty()) { + dest.push_back('['); + mdc_formatter_.format_mdc(mdc_map, dest); + dest.push_back(']'); + dest.push_back(' '); + } +#endif + // fmt_helper::append_string_view(msg.msg(), dest); + fmt_helper::append_string_view(msg.payload, dest); + } + +private: + std::chrono::seconds cache_timestamp_{0}; + memory_buf_t cached_datetime_; + +#ifndef SPDLOG_NO_TLS + mdc_formatter mdc_formatter_{padding_info {}}; +#endif +}; + +} // namespace details + +SPDLOG_INLINE pattern_formatter::pattern_formatter(std::string pattern, + pattern_time_type time_type, + std::string eol, + custom_flags custom_user_flags) + : pattern_(std::move(pattern)), + eol_(std::move(eol)), + pattern_time_type_(time_type), + need_localtime_(false), + last_log_secs_(0), + custom_handlers_(std::move(custom_user_flags)) { + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + compile_pattern_(pattern_); +} + +// use by default full formatter for if pattern is not given +SPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type, std::string eol) + : pattern_("%+"), + eol_(std::move(eol)), + pattern_time_type_(time_type), + need_localtime_(true), + last_log_secs_(0) { + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + formatters_.push_back(details::make_unique(details::padding_info{})); +} + +SPDLOG_INLINE std::unique_ptr pattern_formatter::clone() const { + custom_flags cloned_custom_formatters; + for (auto &it : custom_handlers_) { + cloned_custom_formatters[it.first] = it.second->clone(); + } + auto cloned = details::make_unique(pattern_, pattern_time_type_, eol_, + std::move(cloned_custom_formatters)); + cloned->need_localtime(need_localtime_); +#if defined(__GNUC__) && __GNUC__ < 5 + return std::move(cloned); +#else + return cloned; +#endif +} + +SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest) { + if (need_localtime_) { + const auto secs = + std::chrono::duration_cast(msg.time.time_since_epoch()); + if (secs != last_log_secs_) { + cached_tm_ = get_time_(msg); + last_log_secs_ = secs; + } + } + + for (auto &f : formatters_) { + f->format(msg, cached_tm_, dest); + } + // write eol + details::fmt_helper::append_string_view(eol_, dest); +} + +SPDLOG_INLINE void pattern_formatter::set_pattern(std::string pattern) { + pattern_ = std::move(pattern); + need_localtime_ = false; + compile_pattern_(pattern_); +} + +SPDLOG_INLINE void pattern_formatter::need_localtime(bool need) { need_localtime_ = need; } + +SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg) { + if (pattern_time_type_ == pattern_time_type::local) { + return details::os::localtime(log_clock::to_time_t(msg.time)); + } + return details::os::gmtime(log_clock::to_time_t(msg.time)); +} + +template +SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding) { + // process custom flags + auto it = custom_handlers_.find(flag); + if (it != custom_handlers_.end()) { + auto custom_handler = it->second->clone(); + custom_handler->set_padding_info(padding); + formatters_.push_back(std::move(custom_handler)); + return; + } + + // process built-in flags + switch (flag) { + case ('+'): // default formatter + formatters_.push_back(details::make_unique(padding)); + need_localtime_ = true; + break; + + case 'n': // logger name + formatters_.push_back(details::make_unique>(padding)); + break; + + case 'l': // level + formatters_.push_back(details::make_unique>(padding)); + break; + + case 'L': // short level + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('t'): // thread id + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('v'): // the message text + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('a'): // weekday + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('A'): // short weekday + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('b'): + case ('h'): // month + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('B'): // short month + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('c'): // datetime + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('C'): // year 2 digits + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('Y'): // year 4 digits + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('D'): + case ('x'): // datetime MM/DD/YY + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('m'): // month 1-12 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('d'): // day of month 1-31 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('H'): // hours 24 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('I'): // hours 12 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('M'): // minutes + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('S'): // seconds + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('e'): // milliseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('f'): // microseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('F'): // nanoseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('E'): // seconds since epoch + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('p'): // am/pm + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('r'): // 12 hour clock 02:55:02 pm + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('R'): // 24-hour HH:MM time + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('T'): + case ('X'): // ISO 8601 time format (HH:MM:SS) + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('z'): // timezone + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('P'): // pid + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('^'): // color range start + formatters_.push_back(details::make_unique(padding)); + break; + + case ('$'): // color range end + formatters_.push_back(details::make_unique(padding)); + break; + + case ('@'): // source location (filename:filenumber) + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('s'): // short source filename - without directory name + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('g'): // full source filename + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('#'): // source line number + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('!'): // source funcname + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('%'): // % char + formatters_.push_back(details::make_unique('%')); + break; + + case ('u'): // elapsed time since last log message in nanos + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('i'): // elapsed time since last log message in micros + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('o'): // elapsed time since last log message in millis + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('O'): // elapsed time since last log message in seconds + formatters_.push_back( + details::make_unique>( + padding)); + break; + +#ifndef SPDLOG_NO_TLS // mdc formatter requires TLS support + case ('&'): + formatters_.push_back(details::make_unique>(padding)); + break; +#endif + + default: // Unknown flag appears as is + auto unknown_flag = details::make_unique(); + + if (!padding.truncate_) { + unknown_flag->add_ch('%'); + unknown_flag->add_ch(flag); + formatters_.push_back((std::move(unknown_flag))); + } + // fix issue #1617 (prev char was '!' and should have been treated as funcname flag + // instead of truncating flag) spdlog::set_pattern("[%10!] %v") => "[ main] some + // message" spdlog::set_pattern("[%3!!] %v") => "[mai] some message" + else { + padding.truncate_ = false; + formatters_.push_back( + details::make_unique>(padding)); + unknown_flag->add_ch(flag); + formatters_.push_back((std::move(unknown_flag))); + } + + break; + } +} + +// Extract given pad spec (e.g. %8X, %=8X, %-8!X, %8!X, %=8!X, %-8!X, %+8!X) +// Advance the given it pass the end of the padding spec found (if any) +// Return padding. +SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_( + std::string::const_iterator &it, std::string::const_iterator end) { + using details::padding_info; + using details::scoped_padder; + const size_t max_width = 64; + if (it == end) { + return padding_info{}; + } + + padding_info::pad_side side; + switch (*it) { + case '-': + side = padding_info::pad_side::right; + ++it; + break; + case '=': + side = padding_info::pad_side::center; + ++it; + break; + default: + side = details::padding_info::pad_side::left; + break; + } + + if (it == end || !std::isdigit(static_cast(*it))) { + return padding_info{}; // no padding if no digit found here + } + + auto width = static_cast(*it) - '0'; + for (++it; it != end && std::isdigit(static_cast(*it)); ++it) { + auto digit = static_cast(*it) - '0'; + width = width * 10 + digit; + } + + // search for the optional truncate marker '!' + bool truncate; + if (it != end && *it == '!') { + truncate = true; + ++it; + } else { + truncate = false; + } + return details::padding_info{std::min(width, max_width), side, truncate}; +} + +SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern) { + auto end = pattern.end(); + std::unique_ptr user_chars; + formatters_.clear(); + for (auto it = pattern.begin(); it != end; ++it) { + if (*it == '%') { + if (user_chars) // append user chars found so far + { + formatters_.push_back(std::move(user_chars)); + } + + auto padding = handle_padspec_(++it, end); + + if (it != end) { + if (padding.enabled()) { + handle_flag_(*it, padding); + } else { + handle_flag_(*it, padding); + } + } else { + break; + } + } else // chars not following the % sign should be displayed as is + { + if (!user_chars) { + user_chars = details::make_unique(); + } + user_chars->add_ch(*it); + } + } + if (user_chars) // append raw chars found so far + { + formatters_.push_back(std::move(user_chars)); + } +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/pattern_formatter.h b/vendor/opensource/log_lib/spdlog/pattern_formatter.h new file mode 100755 index 0000000000000000000000000000000000000000..ececd67322fe0a0046745ece8c463bcb9fae53a8 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/pattern_formatter.h @@ -0,0 +1,118 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace details { + +// padding information. +struct padding_info { + enum class pad_side { left, right, center }; + + padding_info() = default; + padding_info(size_t width, padding_info::pad_side side, bool truncate) + : width_(width), + side_(side), + truncate_(truncate), + enabled_(true) {} + + bool enabled() const { return enabled_; } + size_t width_ = 0; + pad_side side_ = pad_side::left; + bool truncate_ = false; + bool enabled_ = false; +}; + +class SPDLOG_API flag_formatter { +public: + explicit flag_formatter(padding_info padinfo) + : padinfo_(padinfo) {} + flag_formatter() = default; + virtual ~flag_formatter() = default; + virtual void format(const details::log_msg &msg, + const std::tm &tm_time, + memory_buf_t &dest) = 0; + +protected: + padding_info padinfo_; +}; + +} // namespace details + +class SPDLOG_API custom_flag_formatter : public details::flag_formatter { +public: + virtual std::unique_ptr clone() const = 0; + + void set_padding_info(const details::padding_info &padding) { + flag_formatter::padinfo_ = padding; + } +}; + +class SPDLOG_API pattern_formatter final : public formatter { +public: + using custom_flags = std::unordered_map>; + + explicit pattern_formatter(std::string pattern, + pattern_time_type time_type = pattern_time_type::local, + std::string eol = spdlog::details::os::default_eol, + custom_flags custom_user_flags = custom_flags()); + + // use default pattern is not given + explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, + std::string eol = spdlog::details::os::default_eol); + + pattern_formatter(const pattern_formatter &other) = delete; + pattern_formatter &operator=(const pattern_formatter &other) = delete; + + std::unique_ptr clone() const override; + void format(const details::log_msg &msg, memory_buf_t &dest) override; + + template + pattern_formatter &add_flag(char flag, Args &&...args) { + custom_handlers_[flag] = details::make_unique(std::forward(args)...); + return *this; + } + void set_pattern(std::string pattern); + void need_localtime(bool need = true); + +private: + std::string pattern_; + std::string eol_; + pattern_time_type pattern_time_type_; + bool need_localtime_; + std::tm cached_tm_; + std::chrono::seconds last_log_secs_; + std::vector> formatters_; + custom_flags custom_handlers_; + + std::tm get_time_(const details::log_msg &msg); + template + void handle_flag_(char flag, details::padding_info padding); + + // Extract given pad spec (e.g. %8X) + // Advance the given it pass the end of the padding spec found (if any) + // Return padding. + static details::padding_info handle_padspec_(std::string::const_iterator &it, + std::string::const_iterator end); + + void compile_pattern_(const std::string &pattern); +}; +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "pattern_formatter-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/android_sink.h b/vendor/opensource/log_lib/spdlog/sinks/android_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..4435a560a00de6d13c21d386e1bfad67c869c825 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/android_sink.h @@ -0,0 +1,137 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef __ANDROID__ + + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #if !defined(SPDLOG_ANDROID_RETRIES) + #define SPDLOG_ANDROID_RETRIES 2 + #endif + +namespace spdlog { +namespace sinks { + +/* + * Android sink + * (logging using __android_log_write or __android_log_buf_write depending on the specified + * BufferID) + */ +template +class android_sink final : public base_sink { +public: + explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false) + : tag_(std::move(tag)), + use_raw_msg_(use_raw_msg) {} + +protected: + void sink_it_(const details::log_msg &msg) override { + const android_LogPriority priority = convert_to_android_(msg.level); + memory_buf_t formatted; + if (use_raw_msg_) { + details::fmt_helper::append_string_view(msg.payload, formatted); + } else { + base_sink::formatter_->format(msg, formatted); + } + formatted.push_back('\0'); + const char *msg_output = formatted.data(); + + // See system/core/liblog/logger_write.c for explanation of return value + int ret = android_log(priority, tag_.c_str(), msg_output); + if (ret == -EPERM) { + return; // !__android_log_is_loggable + } + int retry_count = 0; + while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) { + details::os::sleep_for_millis(5); + ret = android_log(priority, tag_.c_str(), msg_output); + retry_count++; + } + + if (ret < 0) { + throw_spdlog_ex("logging to Android failed", ret); + } + } + + void flush_() override {} + +private: + // There might be liblog versions used, that do not support __android_log_buf_write. So we only + // compile and link against + // __android_log_buf_write, if user explicitly provides a non-default log buffer. Otherwise, + // when using the default log buffer, always log via __android_log_write. + template + typename std::enable_if(log_id::LOG_ID_MAIN), int>::type android_log( + int prio, const char *tag, const char *text) { + return __android_log_write(prio, tag, text); + } + + template + typename std::enable_if(log_id::LOG_ID_MAIN), int>::type android_log( + int prio, const char *tag, const char *text) { + return __android_log_buf_write(ID, prio, tag, text); + } + + static android_LogPriority convert_to_android_(spdlog::level::level_enum level) { + switch (level) { + case spdlog::level::trace: + return ANDROID_LOG_VERBOSE; + case spdlog::level::debug: + return ANDROID_LOG_DEBUG; + case spdlog::level::info: + return ANDROID_LOG_INFO; + case spdlog::level::warn: + return ANDROID_LOG_WARN; + case spdlog::level::err: + return ANDROID_LOG_ERROR; + case spdlog::level::critical: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_DEFAULT; + } + } + + std::string tag_; + bool use_raw_msg_; +}; + +using android_sink_mt = android_sink; +using android_sink_st = android_sink; + +template +using android_sink_buf_mt = android_sink; +template +using android_sink_buf_st = android_sink; + +} // namespace sinks + +// Create and register android syslog logger + +template +inline std::shared_ptr android_logger_mt(const std::string &logger_name, + const std::string &tag = "spdlog") { + return Factory::template create(logger_name, tag); +} + +template +inline std::shared_ptr android_logger_st(const std::string &logger_name, + const std::string &tag = "spdlog") { + return Factory::template create(logger_name, tag); +} + +} // namespace spdlog + +#endif // __ANDROID__ diff --git a/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..6a23f6c70f5d325a79904f6cae94908820952e1c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink-inl.h @@ -0,0 +1,142 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE ansicolor_sink::ansicolor_sink(FILE *target_file, color_mode mode) + : target_file_(target_file), + mutex_(ConsoleMutex::mutex()), + formatter_(details::make_unique()) + +{ + set_color_mode_(mode); + colors_.at(level::trace) = to_string_(white); + colors_.at(level::debug) = to_string_(cyan); + colors_.at(level::info) = to_string_(green); + colors_.at(level::warn) = to_string_(yellow_bold); + colors_.at(level::err) = to_string_(red_bold); + colors_.at(level::critical) = to_string_(bold_on_red); + colors_.at(level::off) = to_string_(reset); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_color(level::level_enum color_level, + string_view_t color) { + std::lock_guard lock(mutex_); + colors_.at(static_cast(color_level)) = to_string_(color); +} + +template +SPDLOG_INLINE void ansicolor_sink::log(const details::log_msg &msg) { + // Wrap the originally formatted message in color codes. + // If color is not supported in the terminal, log as is instead. + std::lock_guard lock(mutex_); + msg.color_range_start = 0; + msg.color_range_end = 0; + memory_buf_t formatted; + formatter_->format(msg, formatted); + if (should_do_colors_ && msg.color_range_end > msg.color_range_start) { + // before color range + print_range_(formatted, 0, msg.color_range_start); + // in color range + print_ccode_(colors_.at(static_cast(msg.level))); + print_range_(formatted, msg.color_range_start, msg.color_range_end); + print_ccode_(reset); + // after color range + print_range_(formatted, msg.color_range_end, formatted.size()); + } else // no color + { + print_range_(formatted, 0, formatted.size()); + } + fflush(target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::flush() { + std::lock_guard lock(mutex_); + fflush(target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_formatter( + std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template +SPDLOG_INLINE bool ansicolor_sink::should_color() const { + return should_do_colors_; +} + +template +SPDLOG_INLINE void ansicolor_sink::set_color_mode(color_mode mode) { + std::lock_guard lock(mutex_); + set_color_mode_(mode); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_color_mode_(color_mode mode) { + switch (mode) { + case color_mode::always: + should_do_colors_ = true; + return; + case color_mode::automatic: + should_do_colors_ = + details::os::in_terminal(target_file_) && details::os::is_color_terminal(); + return; + case color_mode::never: + should_do_colors_ = false; + return; + default: + should_do_colors_ = false; + } +} + +template +SPDLOG_INLINE void ansicolor_sink::print_ccode_( + const string_view_t &color_code) const { + details::os::fwrite_bytes(color_code.data(), color_code.size(), target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::print_range_(const memory_buf_t &formatted, + size_t start, + size_t end) const { + details::os::fwrite_bytes(formatted.data() + start, end - start, target_file_); +} + +template +SPDLOG_INLINE std::string ansicolor_sink::to_string_(const string_view_t &sv) { + return std::string(sv.data(), sv.size()); +} + +// ansicolor_stdout_sink +template +SPDLOG_INLINE ansicolor_stdout_sink::ansicolor_stdout_sink(color_mode mode) + : ansicolor_sink(stdout, mode) {} + +// ansicolor_stderr_sink +template +SPDLOG_INLINE ansicolor_stderr_sink::ansicolor_stderr_sink(color_mode mode) + : ansicolor_sink(stderr, mode) {} + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink.h b/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..19aa421e6c64aa7ef46b6eec646ae05f0e30e9f0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/ansicolor_sink.h @@ -0,0 +1,116 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/** + * This sink prefixes the output with an ANSI escape sequence color code + * depending on the severity + * of the message. + * If no color terminal detected, omit the escape codes. + */ + +template +class ansicolor_sink : public sink { +public: + using mutex_t = typename ConsoleMutex::mutex_t; + ansicolor_sink(FILE *target_file, color_mode mode); + ~ansicolor_sink() override = default; + + ansicolor_sink(const ansicolor_sink &other) = delete; + ansicolor_sink(ansicolor_sink &&other) = delete; + + ansicolor_sink &operator=(const ansicolor_sink &other) = delete; + ansicolor_sink &operator=(ansicolor_sink &&other) = delete; + + void set_color(level::level_enum color_level, string_view_t color); + void set_color_mode(color_mode mode); + bool should_color() const; + + void log(const details::log_msg &msg) override; + void flush() override; + void set_pattern(const std::string &pattern) final override; + void set_formatter(std::unique_ptr sink_formatter) override; + + // Formatting codes + const string_view_t reset = "\033[m"; + const string_view_t bold = "\033[1m"; + const string_view_t dark = "\033[2m"; + const string_view_t underline = "\033[4m"; + const string_view_t blink = "\033[5m"; + const string_view_t reverse = "\033[7m"; + const string_view_t concealed = "\033[8m"; + const string_view_t clear_line = "\033[K"; + + // Foreground colors + const string_view_t black = "\033[30m"; + const string_view_t red = "\033[31m"; + const string_view_t green = "\033[32m"; + const string_view_t yellow = "\033[33m"; + const string_view_t blue = "\033[34m"; + const string_view_t magenta = "\033[35m"; + const string_view_t cyan = "\033[36m"; + const string_view_t white = "\033[37m"; + + /// Background colors + const string_view_t on_black = "\033[40m"; + const string_view_t on_red = "\033[41m"; + const string_view_t on_green = "\033[42m"; + const string_view_t on_yellow = "\033[43m"; + const string_view_t on_blue = "\033[44m"; + const string_view_t on_magenta = "\033[45m"; + const string_view_t on_cyan = "\033[46m"; + const string_view_t on_white = "\033[47m"; + + /// Bold colors + const string_view_t yellow_bold = "\033[33m\033[1m"; + const string_view_t red_bold = "\033[31m\033[1m"; + const string_view_t bold_on_red = "\033[1m\033[41m"; + +private: + FILE *target_file_; + mutex_t &mutex_; + bool should_do_colors_; + std::unique_ptr formatter_; + std::array colors_; + void set_color_mode_(color_mode mode); + void print_ccode_(const string_view_t &color_code) const; + void print_range_(const memory_buf_t &formatted, size_t start, size_t end) const; + static std::string to_string_(const string_view_t &sv); +}; + +template +class ansicolor_stdout_sink : public ansicolor_sink { +public: + explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template +class ansicolor_stderr_sink : public ansicolor_sink { +public: + explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using ansicolor_stdout_sink_mt = ansicolor_stdout_sink; +using ansicolor_stdout_sink_st = ansicolor_stdout_sink; + +using ansicolor_stderr_sink_mt = ansicolor_stderr_sink; +using ansicolor_stderr_sink_st = ansicolor_stderr_sink; + +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "ansicolor_sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/base_sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/base_sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..ada161bcc1d8f590f7a130ffdef71ad58f3ae10d --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/base_sink-inl.h @@ -0,0 +1,59 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +template +SPDLOG_INLINE spdlog::sinks::base_sink::base_sink() + : formatter_{details::make_unique()} {} + +template +SPDLOG_INLINE spdlog::sinks::base_sink::base_sink( + std::unique_ptr formatter) + : formatter_{std::move(formatter)} {} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg) { + std::lock_guard lock(mutex_); + sink_it_(msg); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::flush() { + std::lock_guard lock(mutex_); + flush_(); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + set_pattern_(pattern); +} + +template +void SPDLOG_INLINE +spdlog::sinks::base_sink::set_formatter(std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + set_formatter_(std::move(sink_formatter)); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern_(const std::string &pattern) { + set_formatter_(details::make_unique(pattern)); +} + +template +void SPDLOG_INLINE +spdlog::sinks::base_sink::set_formatter_(std::unique_ptr sink_formatter) { + formatter_ = std::move(sink_formatter); +} diff --git a/vendor/opensource/log_lib/spdlog/sinks/base_sink.h b/vendor/opensource/log_lib/spdlog/sinks/base_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..1b4bb0689b8b6c83d4410677b6c988a4029434a3 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/base_sink.h @@ -0,0 +1,51 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +// +// base sink templated over a mutex (either dummy or real) +// concrete implementation should override the sink_it_() and flush_() methods. +// locking is taken care of in this class - no locking needed by the +// implementers.. +// + +#include +#include +#include + +namespace spdlog { +namespace sinks { +template +class SPDLOG_API base_sink : public sink { +public: + base_sink(); + explicit base_sink(std::unique_ptr formatter); + ~base_sink() override = default; + + base_sink(const base_sink &) = delete; + base_sink(base_sink &&) = delete; + + base_sink &operator=(const base_sink &) = delete; + base_sink &operator=(base_sink &&) = delete; + + void log(const details::log_msg &msg) final override; + void flush() final override; + void set_pattern(const std::string &pattern) final override; + void set_formatter(std::unique_ptr sink_formatter) final override; + +protected: + // sink formatter + std::unique_ptr formatter_; + Mutex mutex_; + + virtual void sink_it_(const details::log_msg &msg) = 0; + virtual void flush_() = 0; + virtual void set_pattern_(const std::string &pattern); + virtual void set_formatter_(std::unique_ptr sink_formatter); +}; +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "base_sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..ce0ddad00686a862db31b62827ab9201ab75e376 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink-inl.h @@ -0,0 +1,48 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, + bool truncate, + const file_event_handlers &event_handlers) + : file_helper_{event_handlers} { + file_helper_.open(filename, truncate); +} + +template +SPDLOG_INLINE const filename_t &basic_file_sink::filename() const { + return file_helper_.filename(); +} + +template +SPDLOG_INLINE void basic_file_sink::truncate() { + std::lock_guard lock(base_sink::mutex_); + file_helper_.reopen(true); +} + +template +SPDLOG_INLINE void basic_file_sink::sink_it_(const details::log_msg &msg) { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); +} + +template +SPDLOG_INLINE void basic_file_sink::flush_() { + file_helper_.flush(); +} + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink.h b/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..48c07671aa42a4af7ecab1b8b862198369863fb1 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/basic_file_sink.h @@ -0,0 +1,66 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Trivial file sink with single file as target + */ +template +class basic_file_sink final : public base_sink { +public: + explicit basic_file_sink(const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}); + const filename_t &filename() const; + void truncate(); + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + +private: + details::file_helper file_helper_; +}; + +using basic_file_sink_mt = basic_file_sink; +using basic_file_sink_st = basic_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr basic_logger_mt(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + event_handlers); +} + +template +inline std::shared_ptr basic_logger_st(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + event_handlers); +} + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "basic_file_sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/callback_sink.h b/vendor/opensource/log_lib/spdlog/sinks/callback_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..8f0c8d4118929b080326862090a50f42646ee3f6 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/callback_sink.h @@ -0,0 +1,56 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include + +namespace spdlog { + +// callbacks type +typedef std::function custom_log_callback; + +namespace sinks { +/* + * Trivial callback sink, gets a callback function and calls it on each log + */ +template +class callback_sink final : public base_sink { +public: + explicit callback_sink(const custom_log_callback &callback) + : callback_{callback} {} + +protected: + void sink_it_(const details::log_msg &msg) override { callback_(msg); } + void flush_() override {} + +private: + custom_log_callback callback_; +}; + +using callback_sink_mt = callback_sink; +using callback_sink_st = callback_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr callback_logger_mt(const std::string &logger_name, + const custom_log_callback &callback) { + return Factory::template create(logger_name, callback); +} + +template +inline std::shared_ptr callback_logger_st(const std::string &logger_name, + const custom_log_callback &callback) { + return Factory::template create(logger_name, callback); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/daily_file_sink.h b/vendor/opensource/log_lib/spdlog/sinks/daily_file_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..615c9f7be3dd74281c3e46112a508aacb814657a --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/daily_file_sink.h @@ -0,0 +1,254 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/* + * Generator of daily log file names in format basename.YYYY-MM-DD.ext + */ +struct daily_filename_calculator { + // Create filename for the form basename.YYYY-MM-DD + static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), + basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, + ext); + } +}; + +/* + * Generator of daily log file names with strftime format. + * Usages: + * auto sink = + * std::make_shared("myapp-%Y-%m-%d:%H:%M:%S.log", hour, + * minute);" auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", + * hour, minute)" + * + */ +struct daily_filename_format_calculator { + static filename_t calc_filename(const filename_t &file_path, const tm &now_tm) { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + std::wstringstream stream; +#else + std::stringstream stream; +#endif + stream << std::put_time(&now_tm, file_path.c_str()); + return stream.str(); + } +}; + +/* + * Rotating file sink based on date. + * If truncate != false , the created file will be truncated. + * If max_files > 0, retain only the last max_files and delete previous. + * Note that old log files from previous executions will not be deleted by this class, + * rotation and deletion is only applied while the program is running. + */ +template +class daily_file_sink final : public base_sink { +public: + // create daily file sink which rotates on given time + daily_file_sink(filename_t base_filename, + int rotation_hour, + int rotation_minute, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) + : base_filename_(std::move(base_filename)), + rotation_h_(rotation_hour), + rotation_m_(rotation_minute), + file_helper_{event_handlers}, + truncate_(truncate), + max_files_(max_files), + filenames_q_() { + if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || + rotation_minute > 59) { + throw_spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); + } + + auto now = log_clock::now(); + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + + if (max_files_ > 0) { + init_filenames_q_(); + } + } + + filename_t filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); + } + +protected: + void sink_it_(const details::log_msg &msg) override { + auto time = msg.time; + bool should_rotate = time >= rotation_tp_; + if (should_rotate) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + } + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); + + // Do the cleaning only at the end because it might throw on failure. + if (should_rotate && max_files_ > 0) { + delete_old_(); + } + } + + void flush_() override { file_helper_.flush(); } + +private: + void init_filenames_q_() { + using details::os::path_exists; + + filenames_q_ = details::circular_q(static_cast(max_files_)); + std::vector filenames; + auto now = log_clock::now(); + while (filenames.size() < max_files_) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + if (!path_exists(filename)) { + break; + } + filenames.emplace_back(filename); + now -= std::chrono::hours(24); + } + for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) { + filenames_q_.push_back(std::move(*iter)); + } + } + + tm now_tm(log_clock::time_point tp) { + time_t tnow = log_clock::to_time_t(tp); + return spdlog::details::os::localtime(tnow); + } + + log_clock::time_point next_rotation_tp_() { + auto now = log_clock::now(); + tm date = now_tm(now); + date.tm_hour = rotation_h_; + date.tm_min = rotation_m_; + date.tm_sec = 0; + auto rotation_time = log_clock::from_time_t(std::mktime(&date)); + if (rotation_time > now) { + return rotation_time; + } + return {rotation_time + std::chrono::hours(24)}; + } + + // Delete the file N rotations ago. + // Throw spdlog_ex on failure to delete the old file. + void delete_old_() { + using details::os::filename_to_str; + using details::os::remove_if_exists; + + filename_t current_file = file_helper_.filename(); + if (filenames_q_.full()) { + auto old_filename = std::move(filenames_q_.front()); + filenames_q_.pop_front(); + bool ok = remove_if_exists(old_filename) == 0; + if (!ok) { + filenames_q_.push_back(std::move(current_file)); + throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), + errno); + } + } + filenames_q_.push_back(std::move(current_file)); + } + + filename_t base_filename_; + int rotation_h_; + int rotation_m_; + log_clock::time_point rotation_tp_; + details::file_helper file_helper_; + bool truncate_; + uint16_t max_files_; + details::circular_q filenames_q_; +}; + +using daily_file_sink_mt = daily_file_sink; +using daily_file_sink_st = daily_file_sink; +using daily_file_format_sink_mt = daily_file_sink; +using daily_file_format_sink_st = + daily_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr daily_logger_mt(const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, hour, minute, + truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_format_mt( + const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_st(const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, hour, minute, + truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_format_st( + const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/dist_sink.h b/vendor/opensource/log_lib/spdlog/sinks/dist_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..69c4971c95344bfef79befecfa26e89f6b9df571 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/dist_sink.h @@ -0,0 +1,81 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "base_sink.h" +#include +#include +#include + +#include +#include +#include +#include + +// Distribution sink (mux). Stores a vector of sinks which get called when log +// is called + +namespace spdlog { +namespace sinks { + +template +class dist_sink : public base_sink { +public: + dist_sink() = default; + explicit dist_sink(std::vector> sinks) + : sinks_(sinks) {} + + dist_sink(const dist_sink &) = delete; + dist_sink &operator=(const dist_sink &) = delete; + + void add_sink(std::shared_ptr sub_sink) { + std::lock_guard lock(base_sink::mutex_); + sinks_.push_back(sub_sink); + } + + void remove_sink(std::shared_ptr sub_sink) { + std::lock_guard lock(base_sink::mutex_); + sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sub_sink), sinks_.end()); + } + + void set_sinks(std::vector> sinks) { + std::lock_guard lock(base_sink::mutex_); + sinks_ = std::move(sinks); + } + + std::vector> &sinks() { return sinks_; } + +protected: + void sink_it_(const details::log_msg &msg) override { + for (auto &sub_sink : sinks_) { + if (sub_sink->should_log(msg.level)) { + sub_sink->log(msg); + } + } + } + + void flush_() override { + for (auto &sub_sink : sinks_) { + sub_sink->flush(); + } + } + + void set_pattern_(const std::string &pattern) override { + set_formatter_(details::make_unique(pattern)); + } + + void set_formatter_(std::unique_ptr sink_formatter) override { + base_sink::formatter_ = std::move(sink_formatter); + for (auto &sub_sink : sinks_) { + sub_sink->set_formatter(base_sink::formatter_->clone()); + } + } + std::vector> sinks_; +}; + +using dist_sink_mt = dist_sink; +using dist_sink_st = dist_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/dup_filter_sink.h b/vendor/opensource/log_lib/spdlog/sinks/dup_filter_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..0588d77217238f3b26915a53a87af7664139d4ce --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/dup_filter_sink.h @@ -0,0 +1,91 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "dist_sink.h" +#include +#include + +#include +#include +#include +#include + +// Duplicate message removal sink. +// Skip the message if previous one is identical and less than "max_skip_duration" have passed +// +// Example: +// +// #include +// +// int main() { +// auto dup_filter = std::make_shared(std::chrono::seconds(5), +// level::info); dup_filter->add_sink(std::make_shared()); +// spdlog::logger l("logger", dup_filter); +// l.info("Hello"); +// l.info("Hello"); +// l.info("Hello"); +// l.info("Different Hello"); +// } +// +// Will produce: +// [2019-06-25 17:50:56.511] [logger] [info] Hello +// [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages.. +// [2019-06-25 17:50:56.512] [logger] [info] Different Hello + +namespace spdlog { +namespace sinks { +template +class dup_filter_sink : public dist_sink { +public: + template + explicit dup_filter_sink(std::chrono::duration max_skip_duration) + : max_skip_duration_{max_skip_duration} {} + +protected: + std::chrono::microseconds max_skip_duration_; + log_clock::time_point last_msg_time_; + std::string last_msg_payload_; + size_t skip_counter_ = 0; + level::level_enum skipped_msg_log_level_ = spdlog::level::level_enum::off; + + void sink_it_(const details::log_msg &msg) override { + bool filtered = filter_(msg); + if (!filtered) { + skip_counter_ += 1; + skipped_msg_log_level_ = msg.level; + return; + } + + // log the "skipped.." message + if (skip_counter_ > 0) { + char buf[64]; + auto msg_size = ::snprintf(buf, sizeof(buf), "Skipped %u duplicate messages..", + static_cast(skip_counter_)); + if (msg_size > 0 && static_cast(msg_size) < sizeof(buf)) { + details::log_msg skipped_msg{msg.source, msg.logger_name, skipped_msg_log_level_, + string_view_t{buf, static_cast(msg_size)}}; + dist_sink::sink_it_(skipped_msg); + } + } + + // log current message + dist_sink::sink_it_(msg); + last_msg_time_ = msg.time; + skip_counter_ = 0; + last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size()); + } + + // return whether the log msg should be displayed (true) or skipped (false) + bool filter_(const details::log_msg &msg) { + auto filter_duration = msg.time - last_msg_time_; + return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_); + } +}; + +using dup_filter_sink_mt = dup_filter_sink; +using dup_filter_sink_st = dup_filter_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/hourly_file_sink.h b/vendor/opensource/log_lib/spdlog/sinks/hourly_file_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..3e618725baedb498c5b4979275b7bfc03544a1ab --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/hourly_file_sink.h @@ -0,0 +1,193 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/* + * Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext + */ +struct hourly_filename_calculator { + // Create filename for the form basename.YYYY-MM-DD-H + static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}{}"), basename, + now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, + now_tm.tm_hour, ext); + } +}; + +/* + * Rotating file sink based on time. + * If truncate != false , the created file will be truncated. + * If max_files > 0, retain only the last max_files and delete previous. + * Note that old log files from previous executions will not be deleted by this class, + * rotation and deletion is only applied while the program is running. + */ +template +class hourly_file_sink final : public base_sink { +public: + // create hourly file sink which rotates on given time + hourly_file_sink(filename_t base_filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) + : base_filename_(std::move(base_filename)), + file_helper_{event_handlers}, + truncate_(truncate), + max_files_(max_files), + filenames_q_() { + auto now = log_clock::now(); + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + file_helper_.open(filename, truncate_); + remove_init_file_ = file_helper_.size() == 0; + rotation_tp_ = next_rotation_tp_(); + + if (max_files_ > 0) { + init_filenames_q_(); + } + } + + filename_t filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); + } + +protected: + void sink_it_(const details::log_msg &msg) override { + auto time = msg.time; + bool should_rotate = time >= rotation_tp_; + if (should_rotate) { + if (remove_init_file_) { + file_helper_.close(); + details::os::remove(file_helper_.filename()); + } + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + } + remove_init_file_ = false; + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); + + // Do the cleaning only at the end because it might throw on failure. + if (should_rotate && max_files_ > 0) { + delete_old_(); + } + } + + void flush_() override { file_helper_.flush(); } + +private: + void init_filenames_q_() { + using details::os::path_exists; + + filenames_q_ = details::circular_q(static_cast(max_files_)); + std::vector filenames; + auto now = log_clock::now(); + while (filenames.size() < max_files_) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + if (!path_exists(filename)) { + break; + } + filenames.emplace_back(filename); + now -= std::chrono::hours(1); + } + for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) { + filenames_q_.push_back(std::move(*iter)); + } + } + + tm now_tm(log_clock::time_point tp) { + time_t tnow = log_clock::to_time_t(tp); + return spdlog::details::os::localtime(tnow); + } + + log_clock::time_point next_rotation_tp_() { + auto now = log_clock::now(); + tm date = now_tm(now); + date.tm_min = 0; + date.tm_sec = 0; + auto rotation_time = log_clock::from_time_t(std::mktime(&date)); + if (rotation_time > now) { + return rotation_time; + } + return {rotation_time + std::chrono::hours(1)}; + } + + // Delete the file N rotations ago. + // Throw spdlog_ex on failure to delete the old file. + void delete_old_() { + using details::os::filename_to_str; + using details::os::remove_if_exists; + + filename_t current_file = file_helper_.filename(); + if (filenames_q_.full()) { + auto old_filename = std::move(filenames_q_.front()); + filenames_q_.pop_front(); + bool ok = remove_if_exists(old_filename) == 0; + if (!ok) { + filenames_q_.push_back(std::move(current_file)); + SPDLOG_THROW(spdlog_ex( + "Failed removing hourly file " + filename_to_str(old_filename), errno)); + } + } + filenames_q_.push_back(std::move(current_file)); + } + + filename_t base_filename_; + log_clock::time_point rotation_tp_; + details::file_helper file_helper_; + bool truncate_; + uint16_t max_files_; + details::circular_q filenames_q_; + bool remove_init_file_; +}; + +using hourly_file_sink_mt = hourly_file_sink; +using hourly_file_sink_st = hourly_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr hourly_logger_mt(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + max_files, event_handlers); +} + +template +inline std::shared_ptr hourly_logger_st(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + max_files, event_handlers); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/kafka_sink.h b/vendor/opensource/log_lib/spdlog/sinks/kafka_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..91e987865a229d717db41b220e1ffcd86a06b307 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/kafka_sink.h @@ -0,0 +1,119 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for kafka +// Building and using requires librdkafka library. +// For building librdkafka library check the url below +// https://github.com/confluentinc/librdkafka +// + +#include "spdlog/async.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/details/null_mutex.h" +#include "spdlog/details/synchronous_factory.h" +#include "spdlog/sinks/base_sink.h" +#include +#include + +// kafka header +#include + +namespace spdlog { +namespace sinks { + +struct kafka_sink_config { + std::string server_addr; + std::string produce_topic; + int32_t flush_timeout_ms = 1000; + + kafka_sink_config(std::string addr, std::string topic, int flush_timeout_ms = 1000) + : server_addr{std::move(addr)}, + produce_topic{std::move(topic)}, + flush_timeout_ms(flush_timeout_ms) {} +}; + +template +class kafka_sink : public base_sink { +public: + kafka_sink(kafka_sink_config config) + : config_{std::move(config)} { + try { + std::string errstr; + conf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL)); + RdKafka::Conf::ConfResult confRes = + conf_->set("bootstrap.servers", config_.server_addr, errstr); + if (confRes != RdKafka::Conf::CONF_OK) { + throw_spdlog_ex( + fmt_lib::format("conf set bootstrap.servers failed err:{}", errstr)); + } + + tconf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC)); + if (tconf_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create topic config failed")); + } + + producer_.reset(RdKafka::Producer::create(conf_.get(), errstr)); + if (producer_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create producer failed err:{}", errstr)); + } + topic_.reset(RdKafka::Topic::create(producer_.get(), config_.produce_topic, + tconf_.get(), errstr)); + if (topic_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create topic failed err:{}", errstr)); + } + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("error create kafka instance: {}", e.what())); + } + } + + ~kafka_sink() { producer_->flush(config_.flush_timeout_ms); } + +protected: + void sink_it_(const details::log_msg &msg) override { + producer_->produce(topic_.get(), 0, RdKafka::Producer::RK_MSG_COPY, + (void *)msg.payload.data(), msg.payload.size(), NULL, NULL); + } + + void flush_() override { producer_->flush(config_.flush_timeout_ms); } + +private: + kafka_sink_config config_; + std::unique_ptr producer_ = nullptr; + std::unique_ptr conf_ = nullptr; + std::unique_ptr tconf_ = nullptr; + std::unique_ptr topic_ = nullptr; +}; + +using kafka_sink_mt = kafka_sink; +using kafka_sink_st = kafka_sink; + +} // namespace sinks + +template +inline std::shared_ptr kafka_logger_mt(const std::string &logger_name, + spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_st(const std::string &logger_name, + spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_async_mt( + std::string logger_name, spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_async_st( + std::string logger_name, spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/mongo_sink.h b/vendor/opensource/log_lib/spdlog/sinks/mongo_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..c5b38ab958453fd1ae2d33f5997f7d5656b02e4b --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/mongo_sink.h @@ -0,0 +1,108 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for mongodb +// Building and using requires mongocxx library. +// For building mongocxx library check the url below +// http://mongocxx.org/mongocxx-v3/installation/ +// + +#include "spdlog/common.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/sinks/base_sink.h" +#include + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { +template +class mongo_sink : public base_sink { +public: + mongo_sink(const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") try + : mongo_sink(std::make_shared(), db_name, collection_name, uri) { + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); + } + + mongo_sink(std::shared_ptr instance, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") + : instance_(std::move(instance)), + db_name_(db_name), + coll_name_(collection_name) { + try { + client_ = spdlog::details::make_unique(mongocxx::uri{uri}); + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); + } + } + + ~mongo_sink() { flush_(); } + +protected: + void sink_it_(const details::log_msg &msg) override { + using bsoncxx::builder::stream::document; + using bsoncxx::builder::stream::finalize; + + if (client_ != nullptr) { + auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" + << level::to_string_view(msg.level).data() << "level_num" + << msg.level << "message" + << std::string(msg.payload.begin(), msg.payload.end()) + << "logger_name" + << std::string(msg.logger_name.begin(), msg.logger_name.end()) + << "thread_id" << static_cast(msg.thread_id) << finalize; + client_->database(db_name_).collection(coll_name_).insert_one(doc.view()); + } + } + + void flush_() override {} + +private: + std::shared_ptr instance_; + std::string db_name_; + std::string coll_name_; + std::unique_ptr client_ = nullptr; +}; + +#include "spdlog/details/null_mutex.h" +#include +using mongo_sink_mt = mongo_sink; +using mongo_sink_st = mongo_sink; + +} // namespace sinks + +template +inline std::shared_ptr mongo_logger_mt( + const std::string &logger_name, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") { + return Factory::template create(logger_name, db_name, collection_name, + uri); +} + +template +inline std::shared_ptr mongo_logger_st( + const std::string &logger_name, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") { + return Factory::template create(logger_name, db_name, collection_name, + uri); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/msvc_sink.h b/vendor/opensource/log_lib/spdlog/sinks/msvc_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..c28d6ebd73867e7da8943e896d8cfbd47dcc38eb --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/msvc_sink.h @@ -0,0 +1,68 @@ +// Copyright(c) 2016 Alexander Dalshov & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#if defined(_WIN32) + + #include + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + #include + #endif + #include + + #include + #include + + // Avoid including windows.h (https://stackoverflow.com/a/30741042) + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringW(const wchar_t *lpOutputString); + #else +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString); + #endif +extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + +namespace spdlog { +namespace sinks { +/* + * MSVC sink (logging using OutputDebugStringA) + */ +template +class msvc_sink : public base_sink { +public: + msvc_sink() = default; + msvc_sink(bool check_debugger_present) + : check_debugger_present_{check_debugger_present} {} + +protected: + void sink_it_(const details::log_msg &msg) override { + if (check_debugger_present_ && !IsDebuggerPresent()) { + return; + } + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + formatted.push_back('\0'); // add a null terminator for OutputDebugString + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + wmemory_buf_t wformatted; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), wformatted); + OutputDebugStringW(wformatted.data()); + #else + OutputDebugStringA(formatted.data()); + #endif + } + + void flush_() override {} + + bool check_debugger_present_ = true; +}; + +using msvc_sink_mt = msvc_sink; +using msvc_sink_st = msvc_sink; + +using windebug_sink_mt = msvc_sink_mt; +using windebug_sink_st = msvc_sink_st; + +} // namespace sinks +} // namespace spdlog + +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/null_sink.h b/vendor/opensource/log_lib/spdlog/sinks/null_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..74530b5b1a32a5b7e681b68d54e1603b9a8fc1ae --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/null_sink.h @@ -0,0 +1,41 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include + +namespace spdlog { +namespace sinks { + +template +class null_sink final : public base_sink { +protected: + void sink_it_(const details::log_msg &) override {} + void flush_() override {} +}; + +using null_sink_mt = null_sink; +using null_sink_st = null_sink; + +} // namespace sinks + +template +inline std::shared_ptr null_logger_mt(const std::string &logger_name) { + auto null_logger = Factory::template create(logger_name); + null_logger->set_level(level::off); + return null_logger; +} + +template +inline std::shared_ptr null_logger_st(const std::string &logger_name) { + auto null_logger = Factory::template create(logger_name); + null_logger->set_level(level::off); + return null_logger; +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/ostream_sink.h b/vendor/opensource/log_lib/spdlog/sinks/ostream_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..6af9dd091e1cc3df8c530f2a9546c775d04c6eeb --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/ostream_sink.h @@ -0,0 +1,43 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +template +class ostream_sink final : public base_sink { +public: + explicit ostream_sink(std::ostream &os, bool force_flush = false) + : ostream_(os), + force_flush_(force_flush) {} + ostream_sink(const ostream_sink &) = delete; + ostream_sink &operator=(const ostream_sink &) = delete; + +protected: + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + ostream_.write(formatted.data(), static_cast(formatted.size())); + if (force_flush_) { + ostream_.flush(); + } + } + + void flush_() override { ostream_.flush(); } + + std::ostream &ostream_; + bool force_flush_; +}; + +using ostream_sink_mt = ostream_sink; +using ostream_sink_st = ostream_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/qt_sinks.h b/vendor/opensource/log_lib/spdlog/sinks/qt_sinks.h new file mode 100755 index 0000000000000000000000000000000000000000..d319e84734c0c3fc488ce41882b962fdc0ac2c43 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/qt_sinks.h @@ -0,0 +1,304 @@ +// Copyright(c) 2015-present, Gabi Melman, mguludag and spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for QPlainTextEdit or QTextEdit and its children (QTextBrowser... +// etc) Building and using requires Qt library. +// +// Warning: the qt_sink won't be notified if the target widget is destroyed. +// If the widget's lifetime can be shorter than the logger's one, you should provide some permanent +// QObject, and then use a standard signal/slot. +// + +#include "spdlog/common.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/details/synchronous_factory.h" +#include "spdlog/sinks/base_sink.h" +#include + +#include +#include + +// +// qt_sink class +// +namespace spdlog { +namespace sinks { +template +class qt_sink : public base_sink { +public: + qt_sink(QObject *qt_object, std::string meta_method) + : qt_object_(qt_object), + meta_method_(std::move(meta_method)) { + if (!qt_object_) { + throw_spdlog_ex("qt_sink: qt_object is null"); + } + } + + ~qt_sink() { flush_(); } + +protected: + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + const string_view_t str = string_view_t(formatted.data(), formatted.size()); + QMetaObject::invokeMethod( + qt_object_, meta_method_.c_str(), Qt::AutoConnection, + Q_ARG(QString, QString::fromUtf8(str.data(), static_cast(str.size())).trimmed())); + } + + void flush_() override {} + +private: + QObject *qt_object_ = nullptr; + std::string meta_method_; +}; + +// Qt color sink to QTextEdit. +// Color location is determined by the sink log pattern like in the rest of spdlog sinks. +// Colors can be modified if needed using sink->set_color(level, qtTextCharFormat). +// max_lines is the maximum number of lines that the sink will hold before removing the oldest +// lines. By default, only ascii (latin1) is supported by this sink. Set is_utf8 to true if utf8 +// support is needed. +template +class qt_color_sink : public base_sink { +public: + qt_color_sink(QTextEdit *qt_text_edit, + int max_lines, + bool dark_colors = false, + bool is_utf8 = false) + : qt_text_edit_(qt_text_edit), + max_lines_(max_lines), + is_utf8_(is_utf8) { + if (!qt_text_edit_) { + throw_spdlog_ex("qt_color_text_sink: text_edit is null"); + } + + default_color_ = qt_text_edit_->currentCharFormat(); + // set colors + QTextCharFormat format; + // trace + format.setForeground(dark_colors ? Qt::darkGray : Qt::gray); + colors_.at(level::trace) = format; + // debug + format.setForeground(dark_colors ? Qt::darkCyan : Qt::cyan); + colors_.at(level::debug) = format; + // info + format.setForeground(dark_colors ? Qt::darkGreen : Qt::green); + colors_.at(level::info) = format; + // warn + format.setForeground(dark_colors ? Qt::darkYellow : Qt::yellow); + colors_.at(level::warn) = format; + // err + format.setForeground(Qt::red); + colors_.at(level::err) = format; + // critical + format.setForeground(Qt::white); + format.setBackground(Qt::red); + colors_.at(level::critical) = format; + } + + ~qt_color_sink() { flush_(); } + + void set_default_color(QTextCharFormat format) { + // std::lock_guard lock(base_sink::mutex_); + default_color_ = format; + } + + void set_level_color(level::level_enum color_level, QTextCharFormat format) { + // std::lock_guard lock(base_sink::mutex_); + colors_.at(static_cast(color_level)) = format; + } + + QTextCharFormat &get_level_color(level::level_enum color_level) { + std::lock_guard lock(base_sink::mutex_); + return colors_.at(static_cast(color_level)); + } + + QTextCharFormat &get_default_color() { + std::lock_guard lock(base_sink::mutex_); + return default_color_; + } + +protected: + struct invoke_params { + invoke_params(int max_lines, + QTextEdit *q_text_edit, + QString payload, + QTextCharFormat default_color, + QTextCharFormat level_color, + int color_range_start, + int color_range_end) + : max_lines(max_lines), + q_text_edit(q_text_edit), + payload(std::move(payload)), + default_color(default_color), + level_color(level_color), + color_range_start(color_range_start), + color_range_end(color_range_end) {} + int max_lines; + QTextEdit *q_text_edit; + QString payload; + QTextCharFormat default_color; + QTextCharFormat level_color; + int color_range_start; + int color_range_end; + }; + + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + + const string_view_t str = string_view_t(formatted.data(), formatted.size()); + // apply the color to the color range in the formatted message. + QString payload; + int color_range_start = static_cast(msg.color_range_start); + int color_range_end = static_cast(msg.color_range_end); + if (is_utf8_) { + payload = QString::fromUtf8(str.data(), static_cast(str.size())); + // convert color ranges from byte index to character index. + if (msg.color_range_start < msg.color_range_end) { + color_range_start = QString::fromUtf8(str.data(), msg.color_range_start).size(); + color_range_end = QString::fromUtf8(str.data(), msg.color_range_end).size(); + } + } else { + payload = QString::fromLatin1(str.data(), static_cast(str.size())); + } + + invoke_params params{max_lines_, // max lines + qt_text_edit_, // text edit to append to + std::move(payload), // text to append + default_color_, // default color + colors_.at(msg.level), // color to apply + color_range_start, // color range start + color_range_end}; // color range end + + QMetaObject::invokeMethod( + qt_text_edit_, [params]() { invoke_method_(params); }, Qt::AutoConnection); + } + + void flush_() override {} + + // Add colored text to the text edit widget. This method is invoked in the GUI thread. + // It is a static method to ensure that it is handled correctly even if the sink is destroyed + // prematurely before it is invoked. + + static void invoke_method_(invoke_params params) { + auto *document = params.q_text_edit->document(); + QTextCursor cursor(document); + + // remove first blocks if number of blocks exceeds max_lines + while (document->blockCount() > params.max_lines) { + cursor.select(QTextCursor::BlockUnderCursor); + cursor.removeSelectedText(); + cursor.deleteChar(); // delete the newline after the block + } + + cursor.movePosition(QTextCursor::End); + cursor.setCharFormat(params.default_color); + + // if color range not specified or not not valid, just append the text with default color + if (params.color_range_end <= params.color_range_start) { + cursor.insertText(params.payload); + return; + } + + // insert the text before the color range + cursor.insertText(params.payload.left(params.color_range_start)); + + // insert the colorized text + cursor.setCharFormat(params.level_color); + cursor.insertText(params.payload.mid(params.color_range_start, + params.color_range_end - params.color_range_start)); + + // insert the text after the color range with default format + cursor.setCharFormat(params.default_color); + cursor.insertText(params.payload.mid(params.color_range_end)); + } + + QTextEdit *qt_text_edit_; + int max_lines_; + bool is_utf8_; + QTextCharFormat default_color_; + std::array colors_; +}; + +#include "spdlog/details/null_mutex.h" +#include + +using qt_sink_mt = qt_sink; +using qt_sink_st = qt_sink; +using qt_color_sink_mt = qt_color_sink; +using qt_color_sink_st = qt_color_sink; +} // namespace sinks + +// +// Factory functions +// + +// log to QTextEdit +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QTextEdit *qt_object, + const std::string &meta_method = "append") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QTextEdit *qt_object, + const std::string &meta_method = "append") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +// log to QPlainTextEdit +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QPlainTextEdit *qt_object, + const std::string &meta_method = "appendPlainText") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QPlainTextEdit *qt_object, + const std::string &meta_method = "appendPlainText") { + return Factory::template create(logger_name, qt_object, meta_method); +} +// log to QObject +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QObject *qt_object, + const std::string &meta_method) { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QObject *qt_object, + const std::string &meta_method) { + return Factory::template create(logger_name, qt_object, meta_method); +} + +// log to QTextEdit with colorized output +template +inline std::shared_ptr qt_color_logger_mt(const std::string &logger_name, + QTextEdit *qt_text_edit, + int max_lines, + bool is_utf8 = false) { + return Factory::template create(logger_name, qt_text_edit, max_lines, + false, is_utf8); +} + +template +inline std::shared_ptr qt_color_logger_st(const std::string &logger_name, + QTextEdit *qt_text_edit, + int max_lines, + bool is_utf8 = false) { + return Factory::template create(logger_name, qt_text_edit, max_lines, + false, is_utf8); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/ringbuffer_sink.h b/vendor/opensource/log_lib/spdlog/sinks/ringbuffer_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..6156c6a516bef3098c4e6df4772d5c7c4044948f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/ringbuffer_sink.h @@ -0,0 +1,67 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "spdlog/details/circular_q.h" +#include "spdlog/details/log_msg_buffer.h" +#include "spdlog/details/null_mutex.h" +#include "spdlog/sinks/base_sink.h" + +#include +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Ring buffer sink + */ +template +class ringbuffer_sink final : public base_sink { +public: + explicit ringbuffer_sink(size_t n_items) + : q_{n_items} {} + + std::vector last_raw(size_t lim = 0) { + std::lock_guard lock(base_sink::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector ret; + ret.reserve(n_items); + for (size_t i = (items_available - n_items); i < items_available; i++) { + ret.push_back(q_.at(i)); + } + return ret; + } + + std::vector last_formatted(size_t lim = 0) { + std::lock_guard lock(base_sink::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector ret; + ret.reserve(n_items); + for (size_t i = (items_available - n_items); i < items_available; i++) { + memory_buf_t formatted; + base_sink::formatter_->format(q_.at(i), formatted); + ret.push_back(SPDLOG_BUF_TO_STRING(formatted)); + } + return ret; + } + +protected: + void sink_it_(const details::log_msg &msg) override { + q_.push_back(details::log_msg_buffer{msg}); + } + void flush_() override {} + +private: + details::circular_q q_; +}; + +using ringbuffer_sink_mt = ringbuffer_sink; +using ringbuffer_sink_st = ringbuffer_sink; + +} // namespace sinks + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..b01936969ea278197891c4424767cddf3e346ecb --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink-inl.h @@ -0,0 +1,179 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE rotating_file_sink::rotating_file_sink( + filename_t base_filename, + std::size_t max_size, + std::size_t max_files, + bool rotate_on_open, + const file_event_handlers &event_handlers) + : base_filename_(std::move(base_filename)), + max_size_(max_size), + max_files_(max_files), + file_helper_{event_handlers} { + if (max_size == 0) { + throw_spdlog_ex("rotating sink export_class: max_size arg cannot be zero"); + } + + if (max_files > MaxFiles) { + throw_spdlog_ex("rotating sink export_class: max_files arg cannot exceed MaxFiles"); + } + file_helper_.open(calc_filename(base_filename_, 0)); + current_size_ = file_helper_.size(); // expensive. called only once + if (rotate_on_open && current_size_ > 0) { + rotate_(); + current_size_ = 0; + } +} + +// calc filename according to index and file extension if exists. +// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". +template +SPDLOG_INLINE filename_t rotating_file_sink::calc_filename(const filename_t &filename, + std::size_t index) { + if (index == 0U) { + return filename; + } + + filename_t basename; + filename_t ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}.{}{}")), basename, index, ext); +} + +template +SPDLOG_INLINE filename_t rotating_file_sink::filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); +} + +template +SPDLOG_INLINE void rotating_file_sink::rotate_now() { + std::lock_guard lock(base_sink::mutex_); + rotate_(); +} +template +SPDLOG_INLINE void rotating_file_sink::set_max_size(std::size_t max_size) { + std::lock_guard lock(base_sink::mutex_); + if (max_size == 0) { + throw_spdlog_ex("rotating sink set_max_size: max_size arg cannot be zero"); + } + max_size_ = max_size; +} + +template +SPDLOG_INLINE std::size_t rotating_file_sink::get_max_size() { + std::lock_guard lock(base_sink::mutex_); + return max_size_; +} + +template +SPDLOG_INLINE void rotating_file_sink::set_max_files(std::size_t max_files) { + std::lock_guard lock(base_sink::mutex_); + if (max_files > MaxFiles) { + throw_spdlog_ex("rotating sink set_max_files: max_files arg cannot exceed 200000"); + } + max_files_ = max_files; +} + +template +std::size_t rotating_file_sink::get_max_files() { + std::lock_guard lock(base_sink::mutex_); + return max_files_; +} + +template +SPDLOG_INLINE void rotating_file_sink::sink_it_(const details::log_msg &msg) { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + auto new_size = current_size_ + formatted.size(); + + // rotate if the new estimated file size exceeds max size. + // rotate only if the real size > 0 to better deal with full disk (see issue #2261). + // we only check the real size when new_size > max_size_ because it is relatively expensive. + if (new_size > max_size_) { + file_helper_.flush(); + if (file_helper_.size() > 0) { + rotate_(); + new_size = formatted.size(); + } + } + file_helper_.write(formatted); + current_size_ = new_size; +} + +template +SPDLOG_INLINE void rotating_file_sink::flush_() { + file_helper_.flush(); +} + +// Rotate files: +// log.txt -> log.1.txt +// log.1.txt -> log.2.txt +// log.2.txt -> log.3.txt +// log.3.txt -> delete +template +SPDLOG_INLINE void rotating_file_sink::rotate_() { + using details::os::filename_to_str; + using details::os::path_exists; + + file_helper_.close(); + for (auto i = max_files_; i > 0; --i) { + filename_t src = calc_filename(base_filename_, i - 1); + if (!path_exists(src)) { + continue; + } + filename_t target = calc_filename(base_filename_, i); + + if (!rename_file_(src, target)) { + // if failed try again after a small delay. + // this is a workaround to a windows issue, where very high rotation + // rates can cause the rename to fail with permission denied (because of antivirus?). + details::os::sleep_for_millis(100); + if (!rename_file_(src, target)) { + file_helper_.reopen( + true); // truncate the log file anyway to prevent it to grow beyond its limit! + current_size_ = 0; + throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + + " to " + filename_to_str(target), + errno); + } + } + } + file_helper_.reopen(true); +} + +// delete the target if exists, and rename the src file to target +// return true on success, false otherwise. +template +SPDLOG_INLINE bool rotating_file_sink::rename_file_(const filename_t &src_filename, + const filename_t &target_filename) { + // try to delete the target file in case it already exists. + (void)details::os::remove(target_filename); + return details::os::rename(src_filename, target_filename) == 0; +} + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink.h b/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..72302e69dc64061df44feeae1e8887fb8be4c1f0 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/rotating_file_sink.h @@ -0,0 +1,93 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { + +// +// Rotating file sink based on size +// +template +class rotating_file_sink final : public base_sink { +public: + static constexpr size_t MaxFiles = 200000; + rotating_file_sink(filename_t base_filename, + std::size_t max_size, + std::size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}); + static filename_t calc_filename(const filename_t &filename, std::size_t index); + filename_t filename(); + void rotate_now(); + void set_max_size(std::size_t max_size); + std::size_t get_max_size(); + void set_max_files(std::size_t max_files); + std::size_t get_max_files(); + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + +private: + // Rotate files: + // log.txt -> log.1.txt + // log.1.txt -> log.2.txt + // log.2.txt -> log.3.txt + // log.3.txt -> delete + void rotate_(); + + // delete the target if exists, and rename the src file to target + // return true on success, false otherwise. + bool rename_file_(const filename_t &src_filename, const filename_t &target_filename); + + filename_t base_filename_; + std::size_t max_size_; + std::size_t max_files_; + std::size_t current_size_; + details::file_helper file_helper_; +}; + +using rotating_file_sink_mt = rotating_file_sink; +using rotating_file_sink_st = rotating_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +std::shared_ptr rotating_logger_mt(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); +} + +template +std::shared_ptr rotating_logger_st(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); +} +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "rotating_file_sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..e4b271404fd1e46c33af63eb791a5ac4da2032dd --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/sink-inl.h @@ -0,0 +1,22 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const { + return msg_level >= level_.load(std::memory_order_relaxed); +} + +SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) { + level_.store(log_level, std::memory_order_relaxed); +} + +SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const { + return static_cast(level_.load(std::memory_order_relaxed)); +} diff --git a/vendor/opensource/log_lib/spdlog/sinks/sink.h b/vendor/opensource/log_lib/spdlog/sinks/sink.h new file mode 100755 index 0000000000000000000000000000000000000000..58506853640561a68a7eb68c69518a44bdd1e42c --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/sink.h @@ -0,0 +1,34 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { + +namespace sinks { +class SPDLOG_API sink { +public: + virtual ~sink() = default; + virtual void log(const details::log_msg &msg) = 0; + virtual void flush() = 0; + virtual void set_pattern(const std::string &pattern) = 0; + virtual void set_formatter(std::unique_ptr sink_formatter) = 0; + + void set_level(level::level_enum log_level); + level::level_enum level() const; + bool should_log(level::level_enum msg_level) const; + +protected: + // sink log level - default is all + level_t level_{level::trace}; +}; + +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks-inl.h b/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..166e386145f9d83ee393bf65d6124cb98057e4f9 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks-inl.h @@ -0,0 +1,38 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { + +template +SPDLOG_INLINE std::shared_ptr stdout_color_mt(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stdout_color_st(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_color_mt(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_color_st(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks.h b/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks.h new file mode 100755 index 0000000000000000000000000000000000000000..72991fe0ed49174b1d687250668398722f39f085 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/stdout_color_sinks.h @@ -0,0 +1,49 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include + +namespace spdlog { +namespace sinks { +#ifdef _WIN32 +using stdout_color_sink_mt = wincolor_stdout_sink_mt; +using stdout_color_sink_st = wincolor_stdout_sink_st; +using stderr_color_sink_mt = wincolor_stderr_sink_mt; +using stderr_color_sink_st = wincolor_stderr_sink_st; +#else +using stdout_color_sink_mt = ansicolor_stdout_sink_mt; +using stdout_color_sink_st = ansicolor_stdout_sink_st; +using stderr_color_sink_mt = ansicolor_stderr_sink_mt; +using stderr_color_sink_st = ansicolor_stderr_sink_st; +#endif +} // namespace sinks + +template +std::shared_ptr stdout_color_mt(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stdout_color_st(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stderr_color_mt(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stderr_color_st(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "stdout_color_sinks-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks-inl.h b/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..dcb21d84a73e5386096959e83c14cacbc528a103 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks-inl.h @@ -0,0 +1,127 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include +#include + +#ifdef _WIN32 + // under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675) + // so instead we use ::FileWrite + #include + + #ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp + #include // WriteFile (..) + #endif + + #include // _get_osfhandle(..) + #include // _fileno(..) +#endif // _WIN32 + +namespace spdlog { + +namespace sinks { + +template +SPDLOG_INLINE stdout_sink_base::stdout_sink_base(FILE *file) + : mutex_(ConsoleMutex::mutex()), + file_(file), + formatter_(details::make_unique()) { +#ifdef _WIN32 + // get windows handle from the FILE* object + + handle_ = reinterpret_cast(::_get_osfhandle(::_fileno(file_))); + + // don't throw to support cases where no console is attached, + // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE). + // throw only if non stdout/stderr target is requested (probably regular file and not console). + if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) { + throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno); + } +#endif // _WIN32 +} + +template +SPDLOG_INLINE void stdout_sink_base::log(const details::log_msg &msg) { +#ifdef _WIN32 + if (handle_ == INVALID_HANDLE_VALUE) { + return; + } + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + auto size = static_cast(formatted.size()); + DWORD bytes_written = 0; + bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0; + if (!ok) { + throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + + std::to_string(::GetLastError())); + } +#else + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + details::os::fwrite_bytes(formatted.data(), formatted.size(), file_); +#endif // _WIN32 + ::fflush(file_); // flush every line to terminal +} + +template +SPDLOG_INLINE void stdout_sink_base::flush() { + std::lock_guard lock(mutex_); + fflush(file_); +} + +template +SPDLOG_INLINE void stdout_sink_base::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +SPDLOG_INLINE void stdout_sink_base::set_formatter( + std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +// stdout sink +template +SPDLOG_INLINE stdout_sink::stdout_sink() + : stdout_sink_base(stdout) {} + +// stderr sink +template +SPDLOG_INLINE stderr_sink::stderr_sink() + : stdout_sink_base(stderr) {} + +} // namespace sinks + +// factory methods +template +SPDLOG_INLINE std::shared_ptr stdout_logger_mt(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stdout_logger_st(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_logger_mt(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_logger_st(const std::string &logger_name) { + return Factory::template create(logger_name); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks.h b/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks.h new file mode 100755 index 0000000000000000000000000000000000000000..6ef09968a456d83c45266376a9165739736fd81a --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/stdout_sinks.h @@ -0,0 +1,84 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#endif + +namespace spdlog { + +namespace sinks { + +template +class stdout_sink_base : public sink { +public: + using mutex_t = typename ConsoleMutex::mutex_t; + explicit stdout_sink_base(FILE *file); + ~stdout_sink_base() override = default; + + stdout_sink_base(const stdout_sink_base &other) = delete; + stdout_sink_base(stdout_sink_base &&other) = delete; + + stdout_sink_base &operator=(const stdout_sink_base &other) = delete; + stdout_sink_base &operator=(stdout_sink_base &&other) = delete; + + void log(const details::log_msg &msg) override; + void flush() override; + void set_pattern(const std::string &pattern) override; + + void set_formatter(std::unique_ptr sink_formatter) override; + +protected: + mutex_t &mutex_; + FILE *file_; + std::unique_ptr formatter_; +#ifdef _WIN32 + HANDLE handle_; +#endif // WIN32 +}; + +template +class stdout_sink : public stdout_sink_base { +public: + stdout_sink(); +}; + +template +class stderr_sink : public stdout_sink_base { +public: + stderr_sink(); +}; + +using stdout_sink_mt = stdout_sink; +using stdout_sink_st = stdout_sink; + +using stderr_sink_mt = stderr_sink; +using stderr_sink_st = stderr_sink; + +} // namespace sinks + +// factory methods +template +std::shared_ptr stdout_logger_mt(const std::string &logger_name); + +template +std::shared_ptr stdout_logger_st(const std::string &logger_name); + +template +std::shared_ptr stderr_logger_mt(const std::string &logger_name); + +template +std::shared_ptr stderr_logger_st(const std::string &logger_name); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "stdout_sinks-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/sinks/syslog_sink.h b/vendor/opensource/log_lib/spdlog/sinks/syslog_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..913d41be61cf0124751f4de7dd38a75c4996b731 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/syslog_sink.h @@ -0,0 +1,104 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { +/** + * Sink that write to syslog using the `syscall()` library call. + */ +template +class syslog_sink : public base_sink { +public: + syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting) + : enable_formatting_{enable_formatting}, + syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, + /* spdlog::level::debug */ LOG_DEBUG, + /* spdlog::level::info */ LOG_INFO, + /* spdlog::level::warn */ LOG_WARNING, + /* spdlog::level::err */ LOG_ERR, + /* spdlog::level::critical */ LOG_CRIT, + /* spdlog::level::off */ LOG_INFO}}, + ident_{std::move(ident)} { + // set ident to be program name if empty + ::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility); + } + + ~syslog_sink() override { ::closelog(); } + + syslog_sink(const syslog_sink &) = delete; + syslog_sink &operator=(const syslog_sink &) = delete; + +protected: + void sink_it_(const details::log_msg &msg) override { + string_view_t payload; + memory_buf_t formatted; + if (enable_formatting_) { + base_sink::formatter_->format(msg, formatted); + payload = string_view_t(formatted.data(), formatted.size()); + } else { + payload = msg.payload; + } + + size_t length = payload.size(); + // limit to max int + if (length > static_cast(std::numeric_limits::max())) { + length = static_cast(std::numeric_limits::max()); + } + + ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(length), payload.data()); + } + + void flush_() override {} + bool enable_formatting_ = false; + + // + // Simply maps spdlog's log level to syslog priority level. + // + virtual int syslog_prio_from_level(const details::log_msg &msg) const { + return syslog_levels_.at(static_cast(msg.level)); + } + + using levels_array = std::array; + levels_array syslog_levels_; + +private: + // must store the ident because the man says openlog might use the pointer as + // is and not a string copy + const std::string ident_; +}; + +using syslog_sink_mt = syslog_sink; +using syslog_sink_st = syslog_sink; +} // namespace sinks + +// Create and register a syslog logger +template +inline std::shared_ptr syslog_logger_mt(const std::string &logger_name, + const std::string &syslog_ident = "", + int syslog_option = 0, + int syslog_facility = LOG_USER, + bool enable_formatting = false) { + return Factory::template create(logger_name, syslog_ident, syslog_option, + syslog_facility, enable_formatting); +} + +template +inline std::shared_ptr syslog_logger_st(const std::string &logger_name, + const std::string &syslog_ident = "", + int syslog_option = 0, + int syslog_facility = LOG_USER, + bool enable_formatting = false) { + return Factory::template create(logger_name, syslog_ident, syslog_option, + syslog_facility, enable_formatting); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/systemd_sink.h b/vendor/opensource/log_lib/spdlog/sinks/systemd_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..d2cd55f2e910ec8357564df62b98a666098466ed --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/systemd_sink.h @@ -0,0 +1,121 @@ +// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#ifndef SD_JOURNAL_SUPPRESS_LOCATION + #define SD_JOURNAL_SUPPRESS_LOCATION +#endif +#include + +namespace spdlog { +namespace sinks { + +/** + * Sink that write to systemd journal using the `sd_journal_send()` library call. + */ +template +class systemd_sink : public base_sink { +public: + systemd_sink(std::string ident = "", bool enable_formatting = false) + : ident_{std::move(ident)}, + enable_formatting_{enable_formatting}, + syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, + /* spdlog::level::debug */ LOG_DEBUG, + /* spdlog::level::info */ LOG_INFO, + /* spdlog::level::warn */ LOG_WARNING, + /* spdlog::level::err */ LOG_ERR, + /* spdlog::level::critical */ LOG_CRIT, + /* spdlog::level::off */ LOG_INFO}} {} + + ~systemd_sink() override {} + + systemd_sink(const systemd_sink &) = delete; + systemd_sink &operator=(const systemd_sink &) = delete; + +protected: + const std::string ident_; + bool enable_formatting_ = false; + using levels_array = std::array; + levels_array syslog_levels_; + + void sink_it_(const details::log_msg &msg) override { + int err; + string_view_t payload; + memory_buf_t formatted; + if (enable_formatting_) { + base_sink::formatter_->format(msg, formatted); + payload = string_view_t(formatted.data(), formatted.size()); + } else { + payload = msg.payload; + } + + size_t length = payload.size(); + // limit to max int + if (length > static_cast(std::numeric_limits::max())) { + length = static_cast(std::numeric_limits::max()); + } + + const string_view_t syslog_identifier = ident_.empty() ? msg.logger_name : ident_; + + // Do not send source location if not available + if (msg.source.empty()) { + // Note: function call inside '()' to avoid macro expansion + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), + "PRIORITY=%d", syslog_level(msg.level), +#ifndef SPDLOG_NO_THREAD_ID + "TID=%zu", msg.thread_id, +#endif + "SYSLOG_IDENTIFIER=%.*s", + static_cast(syslog_identifier.size()), + syslog_identifier.data(), nullptr); + } else { + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), + "PRIORITY=%d", syslog_level(msg.level), +#ifndef SPDLOG_NO_THREAD_ID + "TID=%zu", msg.thread_id, +#endif + "SYSLOG_IDENTIFIER=%.*s", + static_cast(syslog_identifier.size()), + syslog_identifier.data(), "CODE_FILE=%s", msg.source.filename, + "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", + msg.source.funcname, nullptr); + } + + if (err) { + throw_spdlog_ex("Failed writing to systemd", errno); + } + } + + int syslog_level(level::level_enum l) { + return syslog_levels_.at(static_cast(l)); + } + + void flush_() override {} +}; + +using systemd_sink_mt = systemd_sink; +using systemd_sink_st = systemd_sink; +} // namespace sinks + +// Create and register a syslog logger +template +inline std::shared_ptr systemd_logger_mt(const std::string &logger_name, + const std::string &ident = "", + bool enable_formatting = false) { + return Factory::template create(logger_name, ident, enable_formatting); +} + +template +inline std::shared_ptr systemd_logger_st(const std::string &logger_name, + const std::string &ident = "", + bool enable_formatting = false) { + return Factory::template create(logger_name, ident, enable_formatting); +} +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/tcp_sink.h b/vendor/opensource/log_lib/spdlog/sinks/tcp_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..2534964549a7f847a7914ccd7cb907c24aa3f2ce --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/tcp_sink.h @@ -0,0 +1,75 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include + +#pragma once + +// Simple tcp client sink +// Connects to remote address and send the formatted log. +// Will attempt to reconnect if connection drops. +// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the +// sink_it_ method. + +namespace spdlog { +namespace sinks { + +struct tcp_sink_config { + std::string server_host; + int server_port; + bool lazy_connect = false; // if true connect on first log call instead of on construction + + tcp_sink_config(std::string host, int port) + : server_host{std::move(host)}, + server_port{port} {} +}; + +template +class tcp_sink : public spdlog::sinks::base_sink { +public: + // connect to tcp host/port or throw if failed + // host can be hostname or ip address + + explicit tcp_sink(tcp_sink_config sink_config) + : config_{std::move(sink_config)} { + if (!config_.lazy_connect) { + this->client_.connect(config_.server_host, config_.server_port); + } + } + + ~tcp_sink() override = default; + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override { + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + if (!client_.is_connected()) { + client_.connect(config_.server_host, config_.server_port); + } + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + tcp_sink_config config_; + details::tcp_client client_; +}; + +using tcp_sink_mt = tcp_sink; +using tcp_sink_st = tcp_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/udp_sink.h b/vendor/opensource/log_lib/spdlog/sinks/udp_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..4bff0fd2c00ff4370344279ef087a562238df72f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/udp_sink.h @@ -0,0 +1,69 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include + +// Simple udp client sink +// Sends formatted log via udp + +namespace spdlog { +namespace sinks { + +struct udp_sink_config { + std::string server_host; + uint16_t server_port; + + udp_sink_config(std::string host, uint16_t port) + : server_host{std::move(host)}, + server_port{port} {} +}; + +template +class udp_sink : public spdlog::sinks::base_sink { +public: + // host can be hostname or ip address + explicit udp_sink(udp_sink_config sink_config) + : client_{sink_config.server_host, sink_config.server_port} {} + + ~udp_sink() override = default; + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override { + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + details::udp_client client_; +}; + +using udp_sink_mt = udp_sink; +using udp_sink_st = udp_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr udp_logger_mt(const std::string &logger_name, + sinks::udp_sink_config skin_config) { + return Factory::template create(logger_name, skin_config); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/win_eventlog_sink.h b/vendor/opensource/log_lib/spdlog/sinks/win_eventlog_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..2c9b582d30ae061908ba975fba7e2ce0d0ec8afc --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/win_eventlog_sink.h @@ -0,0 +1,260 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// Writing to Windows Event Log requires the registry entries below to be present, with the +// following modifications: +// 1. should be replaced with your log name (e.g. your application name) +// 2. should be replaced with the specific source name and the key should be +// duplicated for +// each source used in the application +// +// Since typically modifications of this kind require elevation, it's better to do it as a part of +// setup procedure. The snippet below uses mscoree.dll as the message file as it exists on most of +// the Windows systems anyway and happens to contain the needed resource. +// +// You can also specify a custom message file if needed. +// Please refer to Event Log functions descriptions in MSDN for more details on custom message +// files. + +/*--------------------------------------------------------------------------------------- + +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\] + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\\] +"TypesSupported"=dword:00000007 +"EventMessageFile"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,\ + 00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,\ + 5c,00,6d,00,73,00,63,00,6f,00,72,00,65,00,65,00,2e,00,64,00,6c,00,6c,00,00,\ + 00 + +-----------------------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { + +namespace win_eventlog { + +namespace internal { + +struct local_alloc_t { + HLOCAL hlocal_; + + SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {} + + local_alloc_t(local_alloc_t const &) = delete; + local_alloc_t &operator=(local_alloc_t const &) = delete; + + ~local_alloc_t() SPDLOG_NOEXCEPT { + if (hlocal_) { + LocalFree(hlocal_); + } + } +}; + +/** Windows error */ +struct win32_error : public spdlog_ex { + /** Formats an error report line: "user-message: error-code (system message)" */ + static std::string format(std::string const &user_message, DWORD error_code = GetLastError()) { + std::string system_message; + + local_alloc_t format_message_result{}; + auto format_message_succeeded = + ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&format_message_result.hlocal_, 0, nullptr); + + if (format_message_succeeded && format_message_result.hlocal_) { + system_message = fmt_lib::format(" ({})", (LPSTR)format_message_result.hlocal_); + } + + return fmt_lib::format("{}: {}{}", user_message, error_code, system_message); + } + + explicit win32_error(std::string const &func_name, DWORD error = GetLastError()) + : spdlog_ex(format(func_name, error)) {} +}; + +/** Wrapper for security identifiers (SID) on Windows */ +struct sid_t { + std::vector buffer_; + +public: + sid_t() {} + + /** creates a wrapped SID copy */ + static sid_t duplicate_sid(PSID psid) { + if (!::IsValidSid(psid)) { + throw_spdlog_ex("sid_t::sid_t(): invalid SID received"); + } + + auto const sid_length{::GetLengthSid(psid)}; + + sid_t result; + result.buffer_.resize(sid_length); + if (!::CopySid(sid_length, (PSID)result.as_sid(), psid)) { + SPDLOG_THROW(win32_error("CopySid")); + } + + return result; + } + + /** Retrieves pointer to the internal buffer contents as SID* */ + SID *as_sid() const { return buffer_.empty() ? nullptr : (SID *)buffer_.data(); } + + /** Get SID for the current user */ + static sid_t get_current_user_sid() { + /* create and init RAII holder for process token */ + struct process_token_t { + HANDLE token_handle_ = INVALID_HANDLE_VALUE; + explicit process_token_t(HANDLE process) { + if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_)) { + SPDLOG_THROW(win32_error("OpenProcessToken")); + } + } + + ~process_token_t() { ::CloseHandle(token_handle_); } + + } current_process_token( + ::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here! + + // Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return + // the token size + DWORD tusize = 0; + if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, + &tusize)) { + SPDLOG_THROW(win32_error("GetTokenInformation should fail")); + } + + // get user token + std::vector buffer(static_cast(tusize)); + if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser, + (LPVOID)buffer.data(), tusize, &tusize)) { + SPDLOG_THROW(win32_error("GetTokenInformation")); + } + + // create a wrapper of the SID data as stored in the user token + return sid_t::duplicate_sid(((TOKEN_USER *)buffer.data())->User.Sid); + } +}; + +struct eventlog { + static WORD get_event_type(details::log_msg const &msg) { + switch (msg.level) { + case level::trace: + case level::debug: + return EVENTLOG_SUCCESS; + + case level::info: + return EVENTLOG_INFORMATION_TYPE; + + case level::warn: + return EVENTLOG_WARNING_TYPE; + + case level::err: + case level::critical: + case level::off: + return EVENTLOG_ERROR_TYPE; + + default: + return EVENTLOG_INFORMATION_TYPE; + } + } + + static WORD get_event_category(details::log_msg const &msg) { return (WORD)msg.level; } +}; + +} // namespace internal + +/* + * Windows Event Log sink + */ +template +class win_eventlog_sink : public base_sink { +private: + HANDLE hEventLog_{NULL}; + internal::sid_t current_user_sid_; + std::string source_; + DWORD event_id_; + + HANDLE event_log_handle() { + if (!hEventLog_) { + hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str()); + if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED) { + SPDLOG_THROW(internal::win32_error("RegisterEventSource")); + } + } + + return hEventLog_; + } + +protected: + void sink_it_(const details::log_msg &msg) override { + using namespace internal; + + bool succeeded; + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + formatted.push_back('\0'); + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + wmemory_buf_t buf; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf); + + LPCWSTR lp_wstr = buf.data(); + succeeded = static_cast(::ReportEventW( + event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), + event_id_, current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr)); +#else + LPCSTR lp_str = formatted.data(); + succeeded = static_cast(::ReportEventA( + event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), + event_id_, current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr)); +#endif + + if (!succeeded) { + SPDLOG_THROW(win32_error("ReportEvent")); + } + } + + void flush_() override {} + +public: + win_eventlog_sink(std::string const &source, + DWORD event_id = 1000 /* according to mscoree.dll */) + : source_(source), + event_id_(event_id) { + try { + current_user_sid_ = internal::sid_t::get_current_user_sid(); + } catch (...) { + // get_current_user_sid() is unlikely to fail and if it does, we can still proceed + // without current_user_sid but in the event log the record will have no user name + } + } + + ~win_eventlog_sink() { + if (hEventLog_) DeregisterEventSource(hEventLog_); + } +}; + +} // namespace win_eventlog + +using win_eventlog_sink_mt = win_eventlog::win_eventlog_sink; +using win_eventlog_sink_st = win_eventlog::win_eventlog_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink-inl.h b/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..a9c0fa25c76969dbb3ab5d2e613e1423a0d0fddf --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink-inl.h @@ -0,0 +1,172 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +template +SPDLOG_INLINE wincolor_sink::wincolor_sink(void *out_handle, color_mode mode) + : out_handle_(out_handle), + mutex_(ConsoleMutex::mutex()), + formatter_(details::make_unique()) { + set_color_mode_impl(mode); + // set level colors + colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; // white + colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE; // cyan + colors_[level::info] = FOREGROUND_GREEN; // green + colors_[level::warn] = + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow + colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY; // intense red + colors_[level::critical] = BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE | + FOREGROUND_INTENSITY; // intense white on red background + colors_[level::off] = 0; +} + +template +SPDLOG_INLINE wincolor_sink::~wincolor_sink() { + this->flush(); +} + +// change the color for the given level +template +void SPDLOG_INLINE wincolor_sink::set_color(level::level_enum level, + std::uint16_t color) { + std::lock_guard lock(mutex_); + colors_[static_cast(level)] = color; +} + +template +void SPDLOG_INLINE wincolor_sink::log(const details::log_msg &msg) { + if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE) { + return; + } + + std::lock_guard lock(mutex_); + msg.color_range_start = 0; + msg.color_range_end = 0; + memory_buf_t formatted; + formatter_->format(msg, formatted); + if (should_do_colors_ && msg.color_range_end > msg.color_range_start) { + // before color range + print_range_(formatted, 0, msg.color_range_start); + // in color range + auto orig_attribs = + static_cast(set_foreground_color_(colors_[static_cast(msg.level)])); + print_range_(formatted, msg.color_range_start, msg.color_range_end); + // reset to orig colors + ::SetConsoleTextAttribute(static_cast(out_handle_), orig_attribs); + print_range_(formatted, msg.color_range_end, formatted.size()); + } else // print without colors if color range is invalid (or color is disabled) + { + write_to_file_(formatted); + } +} + +template +void SPDLOG_INLINE wincolor_sink::flush() { + // windows console always flushed? +} + +template +void SPDLOG_INLINE wincolor_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +void SPDLOG_INLINE +wincolor_sink::set_formatter(std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template +void SPDLOG_INLINE wincolor_sink::set_color_mode(color_mode mode) { + std::lock_guard lock(mutex_); + set_color_mode_impl(mode); +} + +template +void SPDLOG_INLINE wincolor_sink::set_color_mode_impl(color_mode mode) { + if (mode == color_mode::automatic) { + // should do colors only if out_handle_ points to actual console. + DWORD console_mode; + bool in_console = ::GetConsoleMode(static_cast(out_handle_), &console_mode) != 0; + should_do_colors_ = in_console; + } else { + should_do_colors_ = mode == color_mode::always ? true : false; + } +} + +// set foreground color and return the orig console attributes (for resetting later) +template +std::uint16_t SPDLOG_INLINE +wincolor_sink::set_foreground_color_(std::uint16_t attribs) { + CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; + if (!::GetConsoleScreenBufferInfo(static_cast(out_handle_), &orig_buffer_info)) { + // just return white if failed getting console info + return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + } + + // change only the foreground bits (lowest 4 bits) + auto new_attribs = static_cast(attribs) | (orig_buffer_info.wAttributes & 0xfff0); + auto ignored = + ::SetConsoleTextAttribute(static_cast(out_handle_), static_cast(new_attribs)); + (void)(ignored); + return static_cast(orig_buffer_info.wAttributes); // return orig attribs +} + +// print a range of formatted message to console +template +void SPDLOG_INLINE wincolor_sink::print_range_(const memory_buf_t &formatted, + size_t start, + size_t end) { + if (end > start) { +#if defined(SPDLOG_UTF8_TO_WCHAR_CONSOLE) + wmemory_buf_t wformatted; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data() + start, end - start), + wformatted); + auto size = static_cast(wformatted.size()); + auto ignored = ::WriteConsoleW(static_cast(out_handle_), wformatted.data(), size, + nullptr, nullptr); +#else + auto size = static_cast(end - start); + auto ignored = ::WriteConsoleA(static_cast(out_handle_), formatted.data() + start, + size, nullptr, nullptr); +#endif + (void)(ignored); + } +} + +template +void SPDLOG_INLINE wincolor_sink::write_to_file_(const memory_buf_t &formatted) { + auto size = static_cast(formatted.size()); + DWORD bytes_written = 0; + auto ignored = ::WriteFile(static_cast(out_handle_), formatted.data(), size, + &bytes_written, nullptr); + (void)(ignored); +} + +// wincolor_stdout_sink +template +SPDLOG_INLINE wincolor_stdout_sink::wincolor_stdout_sink(color_mode mode) + : wincolor_sink(::GetStdHandle(STD_OUTPUT_HANDLE), mode) {} + +// wincolor_stderr_sink +template +SPDLOG_INLINE wincolor_stderr_sink::wincolor_stderr_sink(color_mode mode) + : wincolor_sink(::GetStdHandle(STD_ERROR_HANDLE), mode) {} +} // namespace sinks +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink.h b/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink.h new file mode 100755 index 0000000000000000000000000000000000000000..8ba594cc2b93443579d4e5954d5fe928fe70b2e3 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/sinks/wincolor_sink.h @@ -0,0 +1,82 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Windows color console sink. Uses WriteConsoleA to write to the console with + * colors + */ +template +class wincolor_sink : public sink { +public: + wincolor_sink(void *out_handle, color_mode mode); + ~wincolor_sink() override; + + wincolor_sink(const wincolor_sink &other) = delete; + wincolor_sink &operator=(const wincolor_sink &other) = delete; + + // change the color for the given level + void set_color(level::level_enum level, std::uint16_t color); + void log(const details::log_msg &msg) final override; + void flush() final override; + void set_pattern(const std::string &pattern) override final; + void set_formatter(std::unique_ptr sink_formatter) override final; + void set_color_mode(color_mode mode); + +protected: + using mutex_t = typename ConsoleMutex::mutex_t; + void *out_handle_; + mutex_t &mutex_; + bool should_do_colors_; + std::unique_ptr formatter_; + std::array colors_; + + // set foreground color and return the orig console attributes (for resetting later) + std::uint16_t set_foreground_color_(std::uint16_t attribs); + + // print a range of formatted message to console + void print_range_(const memory_buf_t &formatted, size_t start, size_t end); + + // in case we are redirected to file (not in console mode) + void write_to_file_(const memory_buf_t &formatted); + + void set_color_mode_impl(color_mode mode); +}; + +template +class wincolor_stdout_sink : public wincolor_sink { +public: + explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template +class wincolor_stderr_sink : public wincolor_sink { +public: + explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using wincolor_stdout_sink_mt = wincolor_stdout_sink; +using wincolor_stdout_sink_st = wincolor_stdout_sink; + +using wincolor_stderr_sink_mt = wincolor_stderr_sink; +using wincolor_stderr_sink_st = wincolor_stderr_sink; +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "wincolor_sink-inl.h" +#endif diff --git a/vendor/opensource/log_lib/spdlog/spdlog-inl.h b/vendor/opensource/log_lib/spdlog/spdlog-inl.h new file mode 100755 index 0000000000000000000000000000000000000000..e02081fe393eab1f3c8c71e33aaa07c50211af74 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/spdlog-inl.h @@ -0,0 +1,96 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { + +SPDLOG_INLINE void initialize_logger(std::shared_ptr logger) { + details::registry::instance().initialize_logger(std::move(logger)); +} + +SPDLOG_INLINE std::shared_ptr get(const std::string &name) { + return details::registry::instance().get(name); +} + +SPDLOG_INLINE void set_formatter(std::unique_ptr formatter) { + details::registry::instance().set_formatter(std::move(formatter)); +} + +SPDLOG_INLINE void set_pattern(std::string pattern, pattern_time_type time_type) { + set_formatter( + std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); +} + +SPDLOG_INLINE void enable_backtrace(size_t n_messages) { + details::registry::instance().enable_backtrace(n_messages); +} + +SPDLOG_INLINE void disable_backtrace() { details::registry::instance().disable_backtrace(); } + +SPDLOG_INLINE void dump_backtrace() { default_logger_raw()->dump_backtrace(); } + +SPDLOG_INLINE level::level_enum get_level() { return default_logger_raw()->level(); } + +SPDLOG_INLINE bool should_log(level::level_enum log_level) { + return default_logger_raw()->should_log(log_level); +} + +SPDLOG_INLINE void set_level(level::level_enum log_level) { + details::registry::instance().set_level(log_level); +} + +SPDLOG_INLINE void flush_on(level::level_enum log_level) { + details::registry::instance().flush_on(log_level); +} + +SPDLOG_INLINE void set_error_handler(void (*handler)(const std::string &msg)) { + details::registry::instance().set_error_handler(handler); +} + +SPDLOG_INLINE void register_logger(std::shared_ptr logger) { + details::registry::instance().register_logger(std::move(logger)); +} + +SPDLOG_INLINE void register_or_replace(std::shared_ptr logger) { + details::registry::instance().register_or_replace(std::move(logger)); +} + +SPDLOG_INLINE void apply_all(const std::function)> &fun) { + details::registry::instance().apply_all(fun); +} + +SPDLOG_INLINE void drop(const std::string &name) { details::registry::instance().drop(name); } + +SPDLOG_INLINE void drop_all() { details::registry::instance().drop_all(); } + +SPDLOG_INLINE void shutdown() { details::registry::instance().shutdown(); } + +SPDLOG_INLINE void set_automatic_registration(bool automatic_registration) { + details::registry::instance().set_automatic_registration(automatic_registration); +} + +SPDLOG_INLINE std::shared_ptr default_logger() { + return details::registry::instance().default_logger(); +} + +SPDLOG_INLINE spdlog::logger *default_logger_raw() { + return details::registry::instance().get_default_raw(); +} + +SPDLOG_INLINE void set_default_logger(std::shared_ptr default_logger) { + details::registry::instance().set_default_logger(std::move(default_logger)); +} + +SPDLOG_INLINE void apply_logger_env_levels(std::shared_ptr logger) { + details::registry::instance().apply_logger_env_levels(std::move(logger)); +} + +} // namespace spdlog diff --git a/vendor/opensource/log_lib/spdlog/spdlog.h b/vendor/opensource/log_lib/spdlog/spdlog.h new file mode 100755 index 0000000000000000000000000000000000000000..1a927ffc924474d627ba3e924b67078d10b43f2f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/spdlog.h @@ -0,0 +1,357 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// spdlog main header file. +// see example.cpp for usage example + +#ifndef SPDLOG_H +#define SPDLOG_H + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace spdlog { + +using default_factory = synchronous_factory; + +// Create and register a logger with a templated sink type +// The logger's level, formatter and flush level will be set according to the +// global settings. +// +// Example: +// spdlog::create("logger_name", "dailylog_filename", 11, 59); +template +inline std::shared_ptr create(std::string logger_name, SinkArgs &&...sink_args) { + return default_factory::create(std::move(logger_name), + std::forward(sink_args)...); +} + +// Initialize and register a logger, +// formatter and flush level will be set according the global settings. +// +// Useful for initializing manually created loggers with the global settings. +// +// Example: +// auto mylogger = std::make_shared("mylogger", ...); +// spdlog::initialize_logger(mylogger); +SPDLOG_API void initialize_logger(std::shared_ptr logger); + +// Return an existing logger or nullptr if a logger with such a name doesn't +// exist. +// example: spdlog::get("my_logger")->info("hello {}", "world"); +SPDLOG_API std::shared_ptr get(const std::string &name); + +// Set global formatter. Each sink in each logger will get a clone of this object +SPDLOG_API void set_formatter(std::unique_ptr formatter); + +// Set global format string. +// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); +SPDLOG_API void set_pattern(std::string pattern, + pattern_time_type time_type = pattern_time_type::local); + +// enable global backtrace support +SPDLOG_API void enable_backtrace(size_t n_messages); + +// disable global backtrace support +SPDLOG_API void disable_backtrace(); + +// call dump backtrace on default logger +SPDLOG_API void dump_backtrace(); + +// Get global logging level +SPDLOG_API level::level_enum get_level(); + +// Set the global logging level +SPDLOG_API void set_level(level::level_enum log_level); + +// Determine whether the default logger should log messages with a certain level +SPDLOG_API bool should_log(level::level_enum lvl); + +// Set a global flush level +SPDLOG_API void flush_on(level::level_enum log_level); + +// Start/Restart a periodic flusher thread +// Warning: Use only if all your loggers are thread safe! +template +inline void flush_every(std::chrono::duration interval) { + details::registry::instance().flush_every(interval); +} + +// Set global error handler +SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg)); + +// Register the given logger with the given name +// Will throw if a logger with the same name already exists. +SPDLOG_API void register_logger(std::shared_ptr logger); + +// Register the given logger with the given name +// Will replace any existing logger with the same name. +SPDLOG_API void register_or_replace(std::shared_ptr logger); + +// Apply a user-defined function on all registered loggers +// Example: +// spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); +SPDLOG_API void apply_all(const std::function)> &fun); + +// Drop the reference to the given logger +SPDLOG_API void drop(const std::string &name); + +// Drop all references from the registry +SPDLOG_API void drop_all(); + +// stop any running threads started by spdlog and clean registry loggers +SPDLOG_API void shutdown(); + +// Automatic registration of loggers when using spdlog::create() or spdlog::create_async +SPDLOG_API void set_automatic_registration(bool automatic_registration); + +// API for using default logger (stdout_color_mt), +// e.g.: spdlog::info("Message {}", 1); +// +// The default logger object can be accessed using the spdlog::default_logger(): +// For example, to add another sink to it: +// spdlog::default_logger()->sinks().push_back(some_sink); +// +// The default logger can be replaced using spdlog::set_default_logger(new_logger). +// For example, to replace it with a file logger. +// +// IMPORTANT: +// The default API is thread safe (for _mt loggers), but: +// set_default_logger() *should not* be used concurrently with the default API. +// e.g., do not call set_default_logger() from one thread while calling spdlog::info() from another. + +SPDLOG_API std::shared_ptr default_logger(); + +SPDLOG_API spdlog::logger *default_logger_raw(); + +SPDLOG_API void set_default_logger(std::shared_ptr default_logger); + +// Initialize logger level based on environment configs. +// +// Useful for applying SPDLOG_LEVEL to manually created loggers. +// +// Example: +// auto mylogger = std::make_shared("mylogger", ...); +// spdlog::apply_logger_env_levels(mylogger); +SPDLOG_API void apply_logger_env_levels(std::shared_ptr logger); + +template +inline void log(source_loc source, + level::level_enum lvl, + format_string_t fmt, + Args &&...args) { + default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); +} + +template +inline void log(level::level_enum lvl, format_string_t fmt, Args &&...args) { + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); +} + +template +inline void trace(format_string_t fmt, Args &&...args) { + default_logger_raw()->trace(fmt, std::forward(args)...); +} + +template +inline void debug(format_string_t fmt, Args &&...args) { + default_logger_raw()->debug(fmt, std::forward(args)...); +} + +template +inline void info(format_string_t fmt, Args &&...args) { + default_logger_raw()->info(fmt, std::forward(args)...); +} + +template +inline void warn(format_string_t fmt, Args &&...args) { + default_logger_raw()->warn(fmt, std::forward(args)...); +} + +template +inline void error(format_string_t fmt, Args &&...args) { + default_logger_raw()->error(fmt, std::forward(args)...); +} + +template +inline void critical(format_string_t fmt, Args &&...args) { + default_logger_raw()->critical(fmt, std::forward(args)...); +} + +template +inline void log(source_loc source, level::level_enum lvl, const T &msg) { + default_logger_raw()->log(source, lvl, msg); +} + +template +inline void log(level::level_enum lvl, const T &msg) { + default_logger_raw()->log(lvl, msg); +} + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +template +inline void log(source_loc source, + level::level_enum lvl, + wformat_string_t fmt, + Args &&...args) { + default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); +} + +template +inline void log(level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); +} + +template +inline void trace(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->trace(fmt, std::forward(args)...); +} + +template +inline void debug(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->debug(fmt, std::forward(args)...); +} + +template +inline void info(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->info(fmt, std::forward(args)...); +} + +template +inline void warn(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->warn(fmt, std::forward(args)...); +} + +template +inline void error(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->error(fmt, std::forward(args)...); +} + +template +inline void critical(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->critical(fmt, std::forward(args)...); +} +#endif + +template +inline void trace(const T &msg) { + default_logger_raw()->trace(msg); +} + +template +inline void debug(const T &msg) { + default_logger_raw()->debug(msg); +} + +template +inline void info(const T &msg) { + default_logger_raw()->info(msg); +} + +template +inline void warn(const T &msg) { + default_logger_raw()->warn(msg); +} + +template +inline void error(const T &msg) { + default_logger_raw()->error(msg); +} + +template +inline void critical(const T &msg) { + default_logger_raw()->critical(msg); +} + +} // namespace spdlog + +// +// enable/disable log calls at compile time according to global level. +// +// define SPDLOG_ACTIVE_LEVEL to one of those (before including spdlog.h): +// SPDLOG_LEVEL_TRACE, +// SPDLOG_LEVEL_DEBUG, +// SPDLOG_LEVEL_INFO, +// SPDLOG_LEVEL_WARN, +// SPDLOG_LEVEL_ERROR, +// SPDLOG_LEVEL_CRITICAL, +// SPDLOG_LEVEL_OFF +// + +#ifndef SPDLOG_NO_SOURCE_LOC + #define SPDLOG_LOGGER_CALL(logger, level, ...) \ + (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__) +#else + #define SPDLOG_LOGGER_CALL(logger, level, ...) \ + (logger)->log(spdlog::source_loc{}, level, __VA_ARGS__) +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE + #define SPDLOG_LOGGER_TRACE(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__) + #define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_TRACE(logger, ...) (void)0 + #define SPDLOG_TRACE(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG + #define SPDLOG_LOGGER_DEBUG(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::debug, __VA_ARGS__) + #define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0 + #define SPDLOG_DEBUG(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO + #define SPDLOG_LOGGER_INFO(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::info, __VA_ARGS__) + #define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_INFO(logger, ...) (void)0 + #define SPDLOG_INFO(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN + #define SPDLOG_LOGGER_WARN(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::warn, __VA_ARGS__) + #define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_WARN(logger, ...) (void)0 + #define SPDLOG_WARN(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR + #define SPDLOG_LOGGER_ERROR(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::err, __VA_ARGS__) + #define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_ERROR(logger, ...) (void)0 + #define SPDLOG_ERROR(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL + #define SPDLOG_LOGGER_CRITICAL(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::critical, __VA_ARGS__) + #define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0 + #define SPDLOG_CRITICAL(...) (void)0 +#endif + +#ifdef SPDLOG_HEADER_ONLY + #include "spdlog-inl.h" +#endif + +#endif // SPDLOG_H diff --git a/vendor/opensource/log_lib/spdlog/stopwatch.h b/vendor/opensource/log_lib/spdlog/stopwatch.h new file mode 100755 index 0000000000000000000000000000000000000000..54ab3d3b846651a904f2fe41be77b6828742744e --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/stopwatch.h @@ -0,0 +1,66 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +// Stopwatch support for spdlog (using std::chrono::steady_clock). +// Displays elapsed seconds since construction as double. +// +// Usage: +// +// spdlog::stopwatch sw; +// ... +// spdlog::debug("Elapsed: {} seconds", sw); => "Elapsed 0.005116733 seconds" +// spdlog::info("Elapsed: {:.6} seconds", sw); => "Elapsed 0.005163 seconds" +// +// +// If other units are needed (e.g. millis instead of double), include "fmt/chrono.h" and use +// "duration_cast<..>(sw.elapsed())": +// +// #include +//.. +// using std::chrono::duration_cast; +// using std::chrono::milliseconds; +// spdlog::info("Elapsed {}", duration_cast(sw.elapsed())); => "Elapsed 5ms" + +namespace spdlog { +class stopwatch { + using clock = std::chrono::steady_clock; + std::chrono::time_point start_tp_; + +public: + stopwatch() + : start_tp_{clock::now()} {} + + std::chrono::duration elapsed() const { + return std::chrono::duration(clock::now() - start_tp_); + } + + std::chrono::milliseconds elapsed_ms() const { + return std::chrono::duration_cast(clock::now() - start_tp_); + } + + void reset() { start_tp_ = clock::now(); } +}; +} // namespace spdlog + +// Support for fmt formatting (e.g. "{:012.9}" or just "{}") +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + +template <> +struct formatter : formatter { + template + auto format(const spdlog::stopwatch &sw, FormatContext &ctx) const -> decltype(ctx.out()) { + return formatter::format(sw.elapsed().count(), ctx); + } +}; +} // namespace std diff --git a/vendor/opensource/log_lib/spdlog/tweakme.h b/vendor/opensource/log_lib/spdlog/tweakme.h new file mode 100755 index 0000000000000000000000000000000000000000..d60929878a519a5e0d15498ce13568a57fb552d4 --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/tweakme.h @@ -0,0 +1,148 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +/////////////////////////////////////////////////////////////////////////////// +// +// Edit this file to squeeze more performance, and to customize supported +// features +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. +// This clock is less accurate - can be off by dozens of millis - depending on +// the kernel HZ. +// Uncomment to use it instead of the regular clock. +// +// #define SPDLOG_CLOCK_COARSE +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment if source location logging is not needed. +// This will prevent spdlog from using __FILE__, __LINE__ and SPDLOG_FUNCTION +// +// #define SPDLOG_NO_SOURCE_LOC +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). +// This will prevent spdlog from querying the thread id on each log call. +// +// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is +// on, zero will be logged as thread id. +// +// #define SPDLOG_NO_THREAD_ID +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to prevent spdlog from using thread local storage. +// +// WARNING: if your program forks, UNCOMMENT this flag to prevent undefined +// thread ids in the children logs. +// +// #define SPDLOG_NO_TLS +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to avoid spdlog's usage of atomic log levels +// Use only if your code never modifies a logger's log levels concurrently by +// different threads. +// +// #define SPDLOG_NO_ATOMIC_LEVELS +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to enable usage of wchar_t for file names on Windows. +// +// #define SPDLOG_WCHAR_FILENAMES +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows) +// +// #define SPDLOG_EOL ";-)\n" +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to override default folder separators ("/" or "\\/" under +// Linux/Windows). Each character in the string is treated as a different +// separator. +// +// #define SPDLOG_FOLDER_SEPS "\\" +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to use your own copy of the fmt library instead of spdlog's copy. +// In this case spdlog will try to include so set your -I flag +// accordingly. +// +// #define SPDLOG_FMT_EXTERNAL +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to use C++20 std::format instead of fmt. +// +// #define SPDLOG_USE_STD_FORMAT +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to enable wchar_t support (convert to utf8) +// +// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to prevent child processes from inheriting log file descriptors +// +// #define SPDLOG_PREVENT_CHILD_FD +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to customize level names (e.g. "MY TRACE") +// +// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY +// CRITICAL", "OFF" } +// +// For C++17 use string_view_literals: +// +// #include +// using namespace std::string_view_literals; +// #define SPDLOG_LEVEL_NAMES { "MY TRACE"sv, "MY DEBUG"sv, "MY INFO"sv, "MY WARNING"sv, "MY +// ERROR"sv, "MY CRITICAL"sv, "OFF"sv } +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to customize short level names (e.g. "MT") +// These can be longer than one character. +// +// #define SPDLOG_SHORT_LEVEL_NAMES { "T", "D", "I", "W", "E", "C", "O" } +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to disable default logger creation. +// This might save some (very) small initialization time if no default logger is needed. +// +// #define SPDLOG_DISABLE_DEFAULT_LOGGER +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment and set to compile time level with zero cost (default is INFO). +// Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) will expand to empty statements if not enabled +// +// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment (and change if desired) macro to use for function names. +// This is compiler dependent. +// __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc. +// Defaults to __FUNCTION__ (should work on all compilers) if not defined. +// +// #ifdef __PRETTY_FUNCTION__ +// # define SPDLOG_FUNCTION __PRETTY_FUNCTION__ +// #else +// # define SPDLOG_FUNCTION __FUNCTION__ +// #endif +/////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/opensource/log_lib/spdlog/version.h b/vendor/opensource/log_lib/spdlog/version.h new file mode 100755 index 0000000000000000000000000000000000000000..d89947b59caa5c3d494e6bdd33d63e87b440711f --- /dev/null +++ b/vendor/opensource/log_lib/spdlog/version.h @@ -0,0 +1,11 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#define SPDLOG_VER_MAJOR 1 +#define SPDLOG_VER_MINOR 15 +#define SPDLOG_VER_PATCH 3 + +#define SPDLOG_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch) +#define SPDLOG_VERSION SPDLOG_TO_VERSION(SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH) diff --git a/vendor/opensource/opencv/.gitkeep b/vendor/opensource/opencv/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/calib3d.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/calib3d.hpp index cea71df9793fbd65c11d14389111cc58335cf219..f44dacbedf9d0394767aa76aba1ad18ef99345af 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/calib3d.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/calib3d.hpp @@ -383,110 +383,6 @@ R & t \\ 0 & 1 \end{bmatrix} P_{h_0}.\f] - Homogeneous Transformations, Object frame / Camera frame
-Change of basis or computing the 3D coordinates from one frame to another frame can be achieved easily using -the following notation: - -\f[ -\mathbf{X}_c = \hspace{0.2em} -{}^{c}\mathbf{T}_o \hspace{0.2em} \mathbf{X}_o -\f] - -\f[ -\begin{bmatrix} -X_c \\ -Y_c \\ -Z_c \\ -1 -\end{bmatrix} = -\begin{bmatrix} -{}^{c}\mathbf{R}_o & {}^{c}\mathbf{t}_o \\ -0_{1 \times 3} & 1 -\end{bmatrix} -\begin{bmatrix} -X_o \\ -Y_o \\ -Z_o \\ -1 -\end{bmatrix} -\f] - -For a 3D points (\f$ \mathbf{X}_o \f$) expressed in the object frame, the homogeneous transformation matrix -\f$ {}^{c}\mathbf{T}_o \f$ allows computing the corresponding coordinate (\f$ \mathbf{X}_c \f$) in the camera frame. -This transformation matrix is composed of a 3x3 rotation matrix \f$ {}^{c}\mathbf{R}_o \f$ and a 3x1 translation vector -\f$ {}^{c}\mathbf{t}_o \f$. -The 3x1 translation vector \f$ {}^{c}\mathbf{t}_o \f$ is the position of the object frame in the camera frame and the -3x3 rotation matrix \f$ {}^{c}\mathbf{R}_o \f$ the orientation of the object frame in the camera frame. - -With this simple notation, it is easy to chain the transformations. For instance, to compute the 3D coordinates of a point -expressed in the object frame in the world frame can be done with: - -\f[ -\mathbf{X}_w = \hspace{0.2em} -{}^{w}\mathbf{T}_c \hspace{0.2em} {}^{c}\mathbf{T}_o \hspace{0.2em} -\mathbf{X}_o = -{}^{w}\mathbf{T}_o \hspace{0.2em} \mathbf{X}_o -\f] - -Similarly, computing the inverse transformation can be done with: - -\f[ -\mathbf{X}_o = \hspace{0.2em} -{}^{o}\mathbf{T}_c \hspace{0.2em} \mathbf{X}_c = -\left( {}^{c}\mathbf{T}_o \right)^{-1} \hspace{0.2em} \mathbf{X}_c -\f] - -The inverse of an homogeneous transformation matrix is then: - -\f[ -{}^{o}\mathbf{T}_c = \left( {}^{c}\mathbf{T}_o \right)^{-1} = -\begin{bmatrix} -{}^{c}\mathbf{R}^{\top}_o & - \hspace{0.2em} {}^{c}\mathbf{R}^{\top}_o \hspace{0.2em} {}^{c}\mathbf{t}_o \\ -0_{1 \times 3} & 1 -\end{bmatrix} -\f] - -One can note that the inverse of a 3x3 rotation matrix is directly its matrix transpose. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png) - -This figure summarizes the whole process. The object pose returned for instance by the @ref solvePnP function -or pose from fiducial marker detection is this \f$ {}^{c}\mathbf{T}_o \f$ transformation. - -The camera intrinsic matrix \f$ \mathbf{K} \f$ allows projecting the 3D point expressed in the camera frame onto the image plane -assuming a perspective projection model (pinhole camera model). Image coordinates extracted from classical image processing functions -assume a (u,v) top-left coordinates frame. - -\note -- for an online video course on this topic, see for instance: - - ["3.3.1. Homogeneous Transformation Matrices", Modern Robotics, Kevin M. Lynch and Frank C. Park](https://modernrobotics.northwestern.edu/nu-gm-book-resource/3-3-1-homogeneous-transformation-matrices/) -- the 3x3 rotation matrix is composed of 9 values but describes a 3 dof transformation -- some additional properties of the 3x3 rotation matrix are: - - \f$ \mathrm{det} \left( \mathbf{R} \right) = 1 \f$ - - \f$ \mathbf{R} \mathbf{R}^{\top} = \mathbf{R}^{\top} \mathbf{R} = \mathrm{I}_{3 \times 3} \f$ - - interpolating rotation can be done using the [Slerp (spherical linear interpolation)](https://en.wikipedia.org/wiki/Slerp) method -- quick conversions between the different rotation formalisms can be done using this [online tool](https://www.andre-gaschler.com/rotationconverter/) - - Intrinsic parameters from camera lens specifications
-When dealing with industrial cameras, the camera intrinsic matrix or more precisely \f$ \left(f_x, f_y \right) \f$ -can be deduced, approximated from the camera specifications: - -\f[ -f_x = \frac{f_{\text{mm}}}{\text{pixel_size_in_mm}} = \frac{f_{\text{mm}}}{\text{sensor_size_in_mm} / \text{nb_pixels}} -\f] - -In a same way, the physical focal length can be deduced from the angular field of view: - -\f[ -f_{\text{mm}} = \frac{\text{sensor_size_in_mm}}{2 \times \tan{\frac{\text{fov}}{2}}} -\f] - -This latter conversion can be useful when using a rendering software to mimic a physical camera device. - -@note - - See also #calibrationMatrixValues - - Additional references, notes
@note - Many functions in this module take a camera intrinsic matrix as an input parameter. Although all functions assume the same structure of this parameter, they may name it differently. The @@ -1002,9 +898,7 @@ An example program about homography from the camera displacement Check @ref tutorial_homography "the corresponding tutorial" for more details */ -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences: - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1067,16 +961,14 @@ More information about Perspective-n-Points is described in @ref calib3d_solvePn - point 1: [ squareLength / 2, squareLength / 2, 0] - point 2: [ squareLength / 2, -squareLength / 2, 0] - point 3: [-squareLength / 2, -squareLength / 2, 0] - - With @ref SOLVEPNP_SQPNP input points must be >= 3 + - With @ref SOLVEPNP_SQPNP input points must be >= 3 */ CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE ); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences using the RANSAC scheme to deal with bad matches. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme. @see @ref calib3d_solvePnP @@ -1109,8 +1001,8 @@ projections imagePoints and the projected (using @ref projectPoints ) objectPoin makes the function resistant to outliers. @note - - An example of how to use solvePnPRansac for object detection can be found at - @ref tutorial_real_time_pose + - An example of how to use solvePNPRansac for object detection can be found at + opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/ - The default method used to estimate the camera pose for the Minimal Sample Sets step is #SOLVEPNP_EPNP. Exceptions are: - if you choose #SOLVEPNP_P3P or #SOLVEPNP_AP3P, these methods will be used. @@ -1136,9 +1028,7 @@ CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoint OutputArray rvec, OutputArray tvec, OutputArray inliers, const UsacParams ¶ms=UsacParams()); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from **3** 3D-2D point correspondences. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1231,9 +1121,7 @@ CV_EXPORTS_W void solvePnPRefineVVS( InputArray objectPoints, InputArray imagePo TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON), double VVSlambda = 1); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1304,7 +1192,6 @@ More information is described in @ref calib3d_solvePnP - point 1: [ squareLength / 2, squareLength / 2, 0] - point 2: [ squareLength / 2, -squareLength / 2, 0] - point 3: [-squareLength / 2, -squareLength / 2, 0] - - With @ref SOLVEPNP_SQPNP input points must be >= 3 */ CV_EXPORTS_W int solvePnPGeneric( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, @@ -1385,8 +1272,7 @@ the board to make the detection more robust in various environments. Otherwise, border and the background is dark, the outer black squares cannot be segmented properly and so the square grouping and ordering algorithm fails. -Use the `gen_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the desired checkerboard pattern. +Use gen_pattern.py (@ref tutorial_camera_calibration_pattern) to create checkerboard. */ CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); @@ -1444,9 +1330,8 @@ which are located on the outside of the board. The following figure illustrates a sample checkerboard optimized for the detection. However, any other checkerboard can be used as well. -Use the `gen_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the corresponding checkerboard pattern: -\image html pics/checkerboard_radon.png width=60% +Use gen_pattern.py (@ref tutorial_camera_calibration_pattern) to create checkerboard. +![Checkerboard](pics/checkerboard_radon.png) */ CV_EXPORTS_AS(findChessboardCornersSBWithMeta) bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, @@ -1549,7 +1434,7 @@ struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters { SYMMETRIC_GRID, ASYMMETRIC_GRID }; - CV_PROP_RW GridType gridType; + GridType gridType; CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. @@ -3461,136 +3346,52 @@ public: }; -/** - * @brief Class for computing stereo correspondence using the block matching algorithm, introduced and contributed to OpenCV by K. Konolige. - * @details This class implements a block matching algorithm for stereo correspondence, which is used to compute disparity maps from stereo image pairs. It provides methods to fine-tune parameters such as pre-filtering, texture thresholds, uniqueness ratios, and regions of interest (ROIs) to optimize performance and accuracy. +/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and +contributed to OpenCV by K. Konolige. */ class CV_EXPORTS_W StereoBM : public StereoMatcher { public: - /** - * @brief Pre-filter types for the stereo matching algorithm. - * @details These constants define the type of pre-filtering applied to the images before computing the disparity map. - * - PREFILTER_NORMALIZED_RESPONSE: Uses normalized response for pre-filtering. - * - PREFILTER_XSOBEL: Uses the X-Sobel operator for pre-filtering. - */ - enum { - PREFILTER_NORMALIZED_RESPONSE = 0, ///< Normalized response pre-filter - PREFILTER_XSOBEL = 1 ///< X-Sobel pre-filter - }; + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; - /** - * @brief Gets the type of pre-filtering currently used in the algorithm. - * @return The current pre-filter type: 0 for PREFILTER_NORMALIZED_RESPONSE or 1 for PREFILTER_XSOBEL. - */ CV_WRAP virtual int getPreFilterType() const = 0; - - /** - * @brief Sets the type of pre-filtering used in the algorithm. - * @param preFilterType The type of pre-filter to use. Possible values are: - * - PREFILTER_NORMALIZED_RESPONSE (0): Uses normalized response for pre-filtering. - * - PREFILTER_XSOBEL (1): Uses the X-Sobel operator for pre-filtering. - * @details The pre-filter type affects how the images are prepared before computing the disparity map. Different pre-filtering methods can enhance specific image features or reduce noise, influencing the quality of the disparity map. - */ CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; - /** - * @brief Gets the current size of the pre-filter kernel. - * @return The current pre-filter size. - */ CV_WRAP virtual int getPreFilterSize() const = 0; - - /** - * @brief Sets the size of the pre-filter kernel. - * @param preFilterSize The size of the pre-filter kernel. Must be an odd integer, typically between 5 and 255. - * @details The pre-filter size determines the spatial extent of the pre-filtering operation, which prepares the images for disparity computation by normalizing brightness and enhancing texture. Larger sizes reduce noise but may blur details, while smaller sizes preserve details but are more susceptible to noise. - */ CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; - /** - * @brief Gets the current truncation value for prefiltered pixels. - * @return The current pre-filter cap value. - */ CV_WRAP virtual int getPreFilterCap() const = 0; - - /** - * @brief Sets the truncation value for prefiltered pixels. - * @param preFilterCap The truncation value. Typically in the range [1, 63]. - * @details This value caps the output of the pre-filter to [-preFilterCap, preFilterCap], helping to reduce the impact of noise and outliers in the pre-filtered image. - */ CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; - /** - * @brief Gets the current texture threshold value. - * @return The current texture threshold. - */ CV_WRAP virtual int getTextureThreshold() const = 0; - - /** - * @brief Sets the threshold for filtering low-texture regions. - * @param textureThreshold The threshold value. Must be non-negative. - * @details This parameter filters out regions with low texture, where establishing correspondences is difficult, thus reducing noise in the disparity map. Higher values filter more aggressively but may discard valid information. - */ CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; - /** - * @brief Gets the current uniqueness ratio value. - * @return The current uniqueness ratio. - */ CV_WRAP virtual int getUniquenessRatio() const = 0; - - /** - * @brief Sets the uniqueness ratio for filtering ambiguous matches. - * @param uniquenessRatio The uniqueness ratio value. Typically in the range [5, 15], but can be from 0 to 100. - * @details This parameter ensures that the best match is sufficiently better than the next best match, reducing false positives. Higher values are stricter but may filter out valid matches in difficult regions. - */ CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; - /** - * @brief Gets the current size of the smaller block used for texture check. - * @return The current smaller block size. - */ CV_WRAP virtual int getSmallerBlockSize() const = 0; - - /** - * @brief Sets the size of the smaller block used for texture check. - * @param blockSize The size of the smaller block. Must be an odd integer between 5 and 255. - * @details This parameter determines the size of the block used to compute texture variance. Smaller blocks capture finer details but are more sensitive to noise, while larger blocks are more robust but may miss fine details. - */ CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; - /** - * @brief Gets the current Region of Interest (ROI) for the left image. - * @return The current ROI for the left image. - */ CV_WRAP virtual Rect getROI1() const = 0; - - /** - * @brief Sets the Region of Interest (ROI) for the left image. - * @param roi1 The ROI rectangle for the left image. - * @details By setting the ROI, the stereo matching computation is limited to the specified region, improving performance and potentially accuracy by focusing on relevant parts of the image. - */ CV_WRAP virtual void setROI1(Rect roi1) = 0; - /** - * @brief Gets the current Region of Interest (ROI) for the right image. - * @return The current ROI for the right image. - */ CV_WRAP virtual Rect getROI2() const = 0; - - /** - * @brief Sets the Region of Interest (ROI) for the right image. - * @param roi2 The ROI rectangle for the right image. - * @details Similar to setROI1, this limits the computation to the specified region in the right image. - */ CV_WRAP virtual void setROI2(Rect roi2) = 0; - /** - * @brief Creates StereoBM object - * @param numDisparities The disparity search range. For each pixel, the algorithm will find the best disparity from 0 (default minimum disparity) to numDisparities. The search range can be shifted by changing the minimum disparity. - * @param blockSize The linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is a higher chance for the algorithm to find a wrong correspondence. - * @return A pointer to the created StereoBM object. - * @details The function creates a StereoBM object. You can then call StereoBM::compute() to compute disparity for a specific stereo pair. + /** @brief Creates StereoBM object + + @param numDisparities the disparity search range. For each pixel algorithm will find the best + disparity from 0 (default minimum disparity) to numDisparities. The search range can then be + shifted by changing the minimum disparity. + @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd + (as the block is centered at the current pixel). Larger block size implies smoother, though less + accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher + chance for algorithm to find a wrong correspondence. + + The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for + a specific stereo pair. */ CV_WRAP static Ptr create(int numDisparities = 0, int blockSize = 21); }; @@ -4261,34 +4062,6 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ /** @brief Finds an object pose from 3D-2D point correspondences for fisheye camera moodel. - @param objectPoints Array of object points in the object coordinate space, Nx3 1-channel or - 1xN/Nx1 3-channel, where N is the number of points. vector\ can also be passed here. - @param imagePoints Array of corresponding image points, Nx2 1-channel or 1xN/Nx1 2-channel, - where N is the number of points. vector\ can also be passed here. - @param cameraMatrix Input camera intrinsic matrix \f$\cameramatrix{A}\f$ . - @param distCoeffs Input vector of distortion coefficients (4x1/1x4). - @param rvec Output rotation vector (see @ref Rodrigues ) that, together with tvec, brings points from - the model coordinate system to the camera coordinate system. - @param tvec Output translation vector. - @param useExtrinsicGuess Parameter used for #SOLVEPNP_ITERATIVE. If true (1), the function uses - the provided rvec and tvec values as initial approximations of the rotation and translation - vectors, respectively, and further optimizes them. - @param flags Method for solving a PnP problem: see @ref calib3d_solvePnP_flags - @param criteria Termination criteria for internal undistortPoints call. - The function interally undistorts points with @ref undistortPoints and call @ref cv::solvePnP, - thus the input are very similar. More information about Perspective-n-Points is described in @ref calib3d_solvePnP - for more information. - */ - CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, - InputArray cameraMatrix, InputArray distCoeffs, - OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) - ); - - /** - @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme for fisheye camera moodel. - @param objectPoints Array of object points in the object coordinate space, Nx3 1-channel or 1xN/Nx1 3-channel, where N is the number of points. vector\ can be also passed here. @param imagePoints Array of corresponding image points, Nx2 1-channel or 1xN/Nx1 2-channel, @@ -4301,12 +4074,6 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ @param useExtrinsicGuess Parameter used for #SOLVEPNP_ITERATIVE. If true (1), the function uses the provided rvec and tvec values as initial approximations of the rotation and translation vectors, respectively, and further optimizes them. - @param iterationsCount Number of iterations. - @param reprojectionError Inlier threshold value used by the RANSAC procedure. The parameter value - is the maximum allowed distance between the observed and computed point projections to consider it - an inlier. - @param confidence The probability that the algorithm produces a useful result. - @param inliers Output vector that contains indices of inliers in objectPoints and imagePoints . @param flags Method for solving a PnP problem: see @ref calib3d_solvePnP_flags This function returns the rotation and the translation vectors that transform a 3D point expressed in the object coordinate frame to the camera coordinate frame, using different methods: @@ -4324,14 +4091,12 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ thus the input are very similar. More information about Perspective-n-Points is described in @ref calib3d_solvePnP for more information. */ - CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints, - InputArray cameraMatrix, InputArray distCoeffs, - OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess = false, int iterationsCount = 100, - float reprojectionError = 8.0, double confidence = 0.99, - OutputArray inliers = noArray(), int flags = SOLVEPNP_ITERATIVE, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) - ); + CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray rvec, OutputArray tvec, + bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE, + TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) + ); //! @} calib3d_fisheye } // end namespace fisheye diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core.hpp index 153bd1732025fdd060e3ace9a9115a3fe5dfd6f9..dcbdfda08e7209f708e5fefc9365a3da6a3ed970 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core.hpp @@ -57,6 +57,10 @@ #include "opencv2/core/types.hpp" #include "opencv2/core/mat.hpp" #include "opencv2/core/persistence.hpp" +#include "opencv2/core/cust_meta_data_of_mem_block.h" +#include "opencv2/core/cust_log.h" +#include "opencv2/core/cust_mpp_allocator.h" +#include "opencv2/core/cust_init_and_final.h" /** @defgroup core Core functionality @@ -805,11 +809,6 @@ Possible usage with some positive example data: normalize(positiveData, normalizedData_minmax, 1.0, 0.0, NORM_MINMAX); @endcode -@note Due to rounding issues, min-max normalization can result in values outside provided boundaries. -If exact range conformity is needed, following workarounds can be used: -- use double floating point precision (dtype = CV_64F) -- manually clip values (`cv::max(res, left_bound, res)`, `cv::min(res, right_bound, res)` or `np.clip`) - @param src input array. @param dst output array of the same size as src . @param alpha norm value to normalize to or the lower range boundary in case of the range @@ -2009,8 +2008,8 @@ The function solveCubic finds the real roots of a cubic equation: The roots are stored in the roots array. @param coeffs equation coefficients, an array of 3 or 4 elements. -@param roots output array of real roots that has 0, 1, 2 or 3 elements. -@return number of real roots. It can be -1 (all real numbers), 0, 1, 2 or 3. +@param roots output array of real roots that has 1 or 3 elements. +@return number of real roots. It can be 0, 1 or 2. */ CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots); diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/base.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/base.hpp index 63c0a01b50f9d891de2d6b22e4099ec378e1d829..5e63ae370035e3ab39348e1de4fb17ed15ad1231 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/base.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/base.hpp @@ -263,72 +263,8 @@ enum DftFlags { DCT_ROWS = DFT_ROWS }; -/*! Various border types, image boundaries are denoted with the `|` character in the table below, when describing each method. - -The following examples show the result of the @ref copyMakeBorder call according to different methods. -Input image is `6x4` (width x height) size and the @ref copyMakeBorder function is used with a border size of 2 pixels -in each direction, giving a resulting image of `10x8` resolution. - -@code -Input image: -[[ 0 1 2 3 4 5] - [ 6 7 8 9 10 11] - [12 13 14 15 16 17] - [18 19 20 21 22 23]] - -Border type: BORDER_CONSTANT (a constant value of 255 is used) -[[255 255 255 255 255 255 255 255 255 255] - [255 255 255 255 255 255 255 255 255 255] - [255 255 0 1 2 3 4 5 255 255] - [255 255 6 7 8 9 10 11 255 255] - [255 255 12 13 14 15 16 17 255 255] - [255 255 18 19 20 21 22 23 255 255] - [255 255 255 255 255 255 255 255 255 255] - [255 255 255 255 255 255 255 255 255 255]] - -Border type: BORDER_REPLICATE -[[ 0 0 0 1 2 3 4 5 5 5] - [ 0 0 0 1 2 3 4 5 5 5] - [ 0 0 0 1 2 3 4 5 5 5] - [ 6 6 6 7 8 9 10 11 11 11] - [12 12 12 13 14 15 16 17 17 17] - [18 18 18 19 20 21 22 23 23 23] - [18 18 18 19 20 21 22 23 23 23] - [18 18 18 19 20 21 22 23 23 23]] - -Border type: BORDER_REFLECT -[[ 7 6 6 7 8 9 10 11 11 10] - [ 1 0 0 1 2 3 4 5 5 4] - [ 1 0 0 1 2 3 4 5 5 4] - [ 7 6 6 7 8 9 10 11 11 10] - [13 12 12 13 14 15 16 17 17 16] - [19 18 18 19 20 21 22 23 23 22] - [19 18 18 19 20 21 22 23 23 22] - [13 12 12 13 14 15 16 17 17 16]] - -Border type: BORDER_WRAP -[[16 17 12 13 14 15 16 17 12 13] - [22 23 18 19 20 21 22 23 18 19] - [ 4 5 0 1 2 3 4 5 0 1] - [10 11 6 7 8 9 10 11 6 7] - [16 17 12 13 14 15 16 17 12 13] - [22 23 18 19 20 21 22 23 18 19] - [ 4 5 0 1 2 3 4 5 0 1] - [10 11 6 7 8 9 10 11 6 7]] - -Border type: BORDER_REFLECT_101 -[[14 13 12 13 14 15 16 17 16 15] - [ 8 7 6 7 8 9 10 11 10 9] - [ 2 1 0 1 2 3 4 5 4 3] - [ 8 7 6 7 8 9 10 11 10 9] - [14 13 12 13 14 15 16 17 16 15] - [20 19 18 19 20 21 22 23 22 21] - [14 13 12 13 14 15 16 17 16 15] - [ 8 7 6 7 8 9 10 11 10 9]] -@endcode - -@see borderInterpolate, copyMakeBorder - */ +//! Various border types, image boundaries are denoted with `|` +//! @see borderInterpolate, copyMakeBorder enum BorderTypes { BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i` BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh` @@ -450,7 +386,7 @@ It does not throw exception, but terminates the application. //! @endcond -#if !defined(NDEBUG) || defined(CV_STATIC_ANALYSIS) +#if defined _DEBUG || defined CV_STATIC_ANALYSIS # define CV_DbgAssert(expr) CV_Assert(expr) #else /** replaced with CV_Assert(expr) in Debug configuration */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cuda.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cuda.hpp index 76b8e6bff1917fbb694dd9b9eeace2dacd6222e7..8191c00783a5c4a4c9d6f32911ab05de2af80c32 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cuda.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cuda.hpp @@ -240,10 +240,6 @@ public: //! converts GpuMat to another datatype (Blocking call) void convertTo(OutputArray dst, int rtype) const; - //! bindings overload which converts GpuMat to another datatype (Blocking call) - CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype) const { - convertTo(static_cast(dst), rtype); - } //! converts GpuMat to another datatype (Non-Blocking call) void convertTo(OutputArray dst, int rtype, Stream& stream) const; @@ -254,13 +250,10 @@ public: //! converts GpuMat to another datatype with scaling (Blocking call) void convertTo(OutputArray dst, int rtype, double alpha, double beta = 0.0) const; - //! bindings overload which converts GpuMat to another datatype with scaling(Blocking call) -#ifdef OPENCV_BINDINGS_PARSER - CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype, double alpha=1.0, double beta = 0.0) const { + CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype, double alpha = 1.0, double beta = 0.0) const { convertTo(static_cast(dst), rtype, alpha, beta); } -#endif //! converts GpuMat to another datatype with scaling (Non-Blocking call) void convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const; diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_init_and_final.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_init_and_final.h new file mode 100644 index 0000000000000000000000000000000000000000..54adad19b4969d9e564c726a36e399d23aeccbbc --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_init_and_final.h @@ -0,0 +1,30 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_INIT_AND_FINAL_H +#define OPENCV_CUST_INIT_AND_FINAL_H + +#include "opencv2/core/cvdef.h" + +namespace cust::mpp::ive{ + // 用来表示初始化工作,有没有完成 + CV_EXPORTS bool inited(); +} + +#endif // OPENCV_CUST_INIT_AND_FINAL_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_log.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_log.h new file mode 100644 index 0000000000000000000000000000000000000000..e2bc895330633a2bc11b80a3c253479860985fc6 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_log.h @@ -0,0 +1,57 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef INC_CUST_LOG_H +#define INC_CUST_LOG_H +#define SPDLOG_HEADER_ONLY +#include "spdlog/sinks/basic_file_sink.h" // 文件输出 +#include "spdlog/sinks/stdout_color_sinks.h" // 控制台输出 +#include "spdlog/spdlog.h" +#include "spdlog/stopwatch.h" +#include "opencv2/core/cvdef.h" +namespace cust { +// 创建csv格式的日志文件 +using t_logger = ::std::shared_ptr; +CV_EXPORTS t_logger csv_logger(); +} // namespace cust + +#define CUST_LOGGER_INFO(...) \ + SPDLOG_LOGGER_INFO(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); \ + //::spdlog::shutdown(); + +#define CUST_LOGGER_WARN(...) \ + SPDLOG_LOGGER_WARN(::cust::csv_logger(), __VA_ARGS__) +#define CUST_LOGGER_ERROR(...) \ + SPDLOG_LOGGER_ERROR(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); \ + +#define CUST_LOGGER_TRACE(...) \ + SPDLOG_LOGGER_TRACE(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#define CUST_LOGGER_DEBUG(...) \ + SPDLOG_LOGGER_DEBUG(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#define CUST_LOGGER_CRITICAL(...) \ + SPDLOG_LOGGER_CRITICAL(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#endif // INC_3_日志的使用_CUST_LOG_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h new file mode 100644 index 0000000000000000000000000000000000000000..148fd9453af50a85637989ac0359f0f1a3fc86f3 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h @@ -0,0 +1,66 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_META_DATA_OF_MEM_BLOCK_H +#define OPENCV_META_DATA_OF_MEM_BLOCK_H + +#include +#include "opencv2/core/cvdef.h" + +namespace cust { +namespace memory { +namespace mpp { +namespace mmz { + +// 这里存放的是MPP的MMZ内存块专用的元数据 +class meta_data_of_mem_block { +public: + //物理地址 + meta_data_of_mem_block(unsigned int len, const char *mmb = nullptr, + const char *zone = nullptr); + ~meta_data_of_mem_block(); + ::std::string txt; +public: + // 输出 + void *phys_addr; // 物理地址 + void *virt_addr; // 虚拟地址 + unsigned int len; // 字节数 +private: + // 输入 + const char *mmb; + const char *zone; + +private: + // 配置 + bool need_free = false; +}; + +} // namespace mmz +} // namespace mpp +} // namespace memory +// 这是一个集查询和设置为一体的enable控制函数 +// operation=0表示查询 +// operation=1表示设置enable为true +// operation=-1表示设置enable为false +// enable控制函数的存在意义是在运行期间,不用重启程序就能够禁用和启用优化。 +// 这样我们才可以编写一个程序:这个程序能够对比优化前后的效果。 +CV_EXPORTS bool enable(int operation=0); +} // namespace cust + +#endif // OPENCV_META_DATA_OF_MEM_BLOCK_H diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_mpp_allocator.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_mpp_allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..6029e1cdd61c45675dbdbfa7da7c1708e7b4bda5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cust_mpp_allocator.h @@ -0,0 +1,70 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_MPP_ALLOCATOR_H +#define OPENCV_CUST_MPP_ALLOCATOR_H + +namespace cust { +namespace mpp { +namespace mmz { +using namespace cv; +class allocator_for_mmz : public ::cv::MatAllocator { +private: + // 以下这两个方法负责内存的申请和释放 + static uchar* alloc(size_t total); + static void free(uchar* pData); +public: + //以下是构造函数,负责把此前的分配器保存起来 + allocator_for_mmz(); + // 重写的第一个API函数:用来向上层分配内存空间 + UMatData *allocate(int dims, const int *sizes, int type, void *data0, + size_t *step, AccessFlag flags, + UMatUsageFlags usageFlags) const override; + // 重写的第二个API函数:用来满足上层的内存释放请求 + void deallocate(UMatData *u) const override; + // 这是三个参数的内存申请函数,到底是干啥的不知道 + bool allocate(UMatData *data, AccessFlag accessflags, + UMatUsageFlags usageFlags) const override; + +private: + // 以下这个用来保存原来的分配器 + MatAllocator *std_allocator; +}; + +// 这个用来初始化和终结化 +// 初始化的目的就是使能 +// 终结化的目的就是禁用 +class init_and_final { +private: + allocator_for_mmz custom_allocator; +public: + init_and_final(); + ~init_and_final(); +}; + + +} // namespace mmz +} // namespace mpp +} // namespace cust + +namespace cv{ + CV_EXPORTS std::shared_ptr cust_mpp_get_meta_data(InputArray data); +} + +#endif // OPENCV_CUST_MPP_ALLOCATOR_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cv_cpu_dispatch.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cv_cpu_dispatch.h index b920ba349eaf420dd3a4cb2543c8ab7c4eb1b9a3..607f2866158427def3e9e4c62723764e25e33220 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cv_cpu_dispatch.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cv_cpu_dispatch.h @@ -72,7 +72,7 @@ # define CV_AVX 1 #endif #ifdef CV_CPU_COMPILE_FP16 -# if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) +# if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) # include # else # include @@ -137,7 +137,7 @@ # define CV_FMA3 1 #endif -#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) +#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) # include # include # define CV_NEON 1 @@ -230,7 +230,7 @@ struct VZeroUpperGuard { # define CV_MMX 1 # define CV_SSE 1 # define CV_SSE2 1 -#elif defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) +#elif defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) # include # include # define CV_NEON 1 diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cvdef.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cvdef.h index 7fea9c0bd60f8d58b4809ee6c2a5aaca6ff20493..0e6d6ff49bc7830015071cd098790d09abeb6ea1 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cvdef.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/cvdef.h @@ -368,7 +368,7 @@ enum CpuFeatures { #include "cv_cpu_dispatch.h" -#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) +#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64)) // int*, int64* should be propertly aligned pointers on ARMv7 #define CV_STRONG_ALIGNMENT 1 #endif @@ -697,7 +697,7 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType) #ifdef CV_XADD // allow to use user-defined macro #elif defined __GNUC__ || defined __clang__ -# if defined __clang__ && __clang_major__ >= 3 && !defined __EMSCRIPTEN__ && !defined __INTEL_COMPILER +# if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) && !defined __INTEL_COMPILER # ifdef __ATOMIC_ACQ_REL # define CV_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) # else diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/fast_math.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/fast_math.hpp index e1363272077a67478909016bb54ce11e54426f81..a28c3fbedfe690f6e8da6c0807aed18302c9b68b 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/fast_math.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/fast_math.hpp @@ -201,10 +201,6 @@ cvRound( double value ) { #if defined CV_INLINE_ROUND_DBL CV_INLINE_ROUND_DBL(value); -#elif defined _MSC_VER && defined _M_ARM64 - float64x1_t v = vdup_n_f64(value); - int64x1_t r = vcvtn_s64_f64(v); - return static_cast(vget_lane_s64(r, 0)); #elif ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __SSE2__)) && !defined(__CUDACC__) __m128d t = _mm_set_sd( value ); return _mm_cvtsd_si32(t); @@ -307,7 +303,7 @@ CV_INLINE int cvIsInf( double value ) { #if defined CV_INLINE_ISINF_DBL CV_INLINE_ISINF_DBL(value); -#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__PPC64__) || defined(__loongarch64) +#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__PPC64__) || defined(__loongarch64) Cv64suf ieee754; ieee754.f = value; return (ieee754.u & 0x7fffffffffffffff) == @@ -327,10 +323,6 @@ CV_INLINE int cvRound(float value) { #if defined CV_INLINE_ROUND_FLT CV_INLINE_ROUND_FLT(value); -#elif defined _MSC_VER && defined _M_ARM64 - float32x2_t v = vdup_n_f32(value); - int32x2_t r = vcvtn_s32_f32(v); - return vget_lane_s32(r, 0); #elif ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __SSE2__)) && !defined(__CUDACC__) __m128 t = _mm_set_ss( value ); return _mm_cvtss_si32(t); diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_cpp.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_cpp.hpp index 9c7922445f32adae3c9cbcfc3d70610768ab366a..3e5d484145aae842d1c02826f87fc840155d420d 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_cpp.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_cpp.hpp @@ -225,30 +225,32 @@ These operations allow to reorder or recombine elements in one or multiple vecto Element-wise binary and unary operations. - Arithmetics: -@ref v_add, -@ref v_sub, -@ref v_mul, -@ref v_div, +@ref v_add(const v_reg &a, const v_reg &b) "+", +@ref v_sub(const v_reg &a, const v_reg &b) "-", +@ref v_mul(const v_reg &a, const v_reg &b) "*", +@ref v_div(const v_reg &a, const v_reg &b) "/", @ref v_mul_expand - Non-saturating arithmetics: @ref v_add_wrap, @ref v_sub_wrap - Bitwise shifts: +@ref v_shl(const v_reg &a, int s) "<<", +@ref v_shr(const v_reg &a, int s) ">>", @ref v_shl, @ref v_shr - Bitwise logic: -@ref v_and, -@ref v_or, -@ref v_xor, -@ref v_not +@ref v_and(const v_reg &a, const v_reg &b) "&", +@ref v_or(const v_reg &a, const v_reg &b) "|", +@ref v_xor(const v_reg &a, const v_reg &b) "^", +@ref v_not(const v_reg &a) "~" - Comparison: -@ref v_gt, -@ref v_ge, -@ref v_lt, -@ref v_le, -@ref v_eq, -@ref v_ne +@ref v_gt(const v_reg &a, const v_reg &b) ">", +@ref v_ge(const v_reg &a, const v_reg &b) ">=", +@ref v_lt(const v_reg &a, const v_reg &b) "<", +@ref v_le(const v_reg &a, const v_reg &b) "<=", +@ref v_eq(const v_reg &a, const v_reg &b) "==", +@ref v_ne(const v_reg &a, const v_reg &b) "!=" - min/max: @ref v_min, @ref v_max diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h deleted file mode 100644 index 764c245df9a994f72419123a5a863efc70ba6649..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h +++ /dev/null @@ -1,111 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html - -// This file has been created for compatibility with older versions of Universal Intrinscs -// Binary operators for vector types has been removed since version 4.11 -// Include this file manually after OpenCV headers if you need these operators - -#ifndef OPENCV_HAL_INTRIN_LEGACY_OPS_HPP -#define OPENCV_HAL_INTRIN_LEGACY_OPS_HPP - -#ifdef __OPENCV_BUILD -#error "Universal Intrinsics operators are deprecated and should not be used in OpenCV library" -#endif - -#ifdef __riscv -#warning "Operators might conflict with built-in functions on RISC-V platform" -#endif - -#if defined(CV_VERSION) && CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR < 9 -#warning "Older versions of OpenCV (<4.9) already have Universal Intrinscs operators" -#endif - - -namespace cv { namespace hal { - -#define BIN_OP(OP, FUN) \ -template R operator OP (const R & lhs, const R & rhs) { return FUN(lhs, rhs); } - -#define BIN_A_OP(OP, FUN) \ -template R & operator OP (R & res, const R & val) { res = FUN(res, val); return res; } - -#define UN_OP(OP, FUN) \ -template R operator OP (const R & val) { return FUN(val); } - -BIN_OP(+, v_add) -BIN_OP(-, v_sub) -BIN_OP(*, v_mul) -BIN_OP(/, v_div) -BIN_OP(&, v_and) -BIN_OP(|, v_or) -BIN_OP(^, v_xor) - -BIN_OP(==, v_eq) -BIN_OP(!=, v_ne) -BIN_OP(<, v_lt) -BIN_OP(>, v_gt) -BIN_OP(<=, v_le) -BIN_OP(>=, v_ge) - -BIN_A_OP(+=, v_add) -BIN_A_OP(-=, v_sub) -BIN_A_OP(*=, v_mul) -BIN_A_OP(/=, v_div) -BIN_A_OP(&=, v_and) -BIN_A_OP(|=, v_or) -BIN_A_OP(^=, v_xor) - -UN_OP(~, v_not) - -// TODO: shift operators? - -}} // cv::hal:: - -//============================================================================== - -#ifdef OPENCV_ENABLE_INLINE_INTRIN_OPERATOR_TEST - -namespace cv { namespace hal { - -inline static void opencv_operator_compile_test() -{ - using namespace cv; - v_float32 a, b, c; - uint8_t shift = 1; - a = b + c; - a = b - c; - a = b * c; - a = b / c; - a = b & c; - a = b | c; - a = b ^ c; - // a = b >> shift; - // a = b << shift; - - a = (b == c); - a = (b != c); - a = (b < c);}} - a = (b > c); - a = (b <= c); - a = (b >= c); - - a += b; - a -= b; - a *= b; - a /= b; - a &= b; - a |= b; - a ^= b; - // a <<= shift; - // a >>= shift; - - a = ~b; -} - -}} // cv::hal:: - -#endif - - -#endif // OPENCV_HAL_INTRIN_LEGACY_OPS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_neon.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_neon.hpp index 3c1630148b80e8b1928d1a409a6ee5d6a7f463fe..64fb7d73bc66a930cdc47e56f0aa7493da14de8a 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_neon.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_neon.hpp @@ -56,7 +56,7 @@ namespace cv CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN #define CV_SIMD128 1 -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) #define CV_SIMD128_64F 1 #else #define CV_SIMD128_64F 0 @@ -72,7 +72,7 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN // // [1] https://developer.arm.com/documentation/101028/0012/13--Advanced-SIMD--Neon--intrinsics // [2] https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros -#if defined(__ARM_64BIT_STATE) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__ARM_64BIT_STATE) || defined(_M_ARM64) #define CV_NEON_AARCH64 1 #else #define CV_NEON_AARCH64 0 @@ -1080,7 +1080,7 @@ OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int16x8, vreinterpretq_s16_u16, s16, u16) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32) -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) static inline uint64x2_t vmvnq_u64(uint64x2_t a) { uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF)); @@ -1822,7 +1822,7 @@ inline v_int32x4 v_load_expand_q(const schar* ptr) return v_int32x4(vmovl_s16(v1)); } -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) #define OPENCV_HAL_IMPL_NEON_UNPACKS(_Tpvec, suffix) \ inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \ { \ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp index 67c9d12741be787d22987a38d1a93e0a0dd75cb2..b6ce2d7f47cc9aa982fb1392401eb041e5e37602 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp @@ -8,7 +8,6 @@ #ifndef OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP #define OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP -#include #include #if defined(__GNUC__) && !defined(__clang__) @@ -63,9 +62,8 @@ struct VTraits \ { \ static inline int vlanes() { return __riscv_vsetvlmax_##SUF(); } \ using lane_type = TYP; \ - static const int max_nlanes = CV_RVV_MAX_VLEN/SZ*2; \ + static const int max_nlanes = CV_RVV_MAX_VLEN/SZ; \ }; -// `max_nlanes` is multiplied by 2 because of using LMUL=2 (m2) OPENCV_HAL_IMPL_RVV_TRAITS(vint8m1_t, int8_t, e8m1, 8) OPENCV_HAL_IMPL_RVV_TRAITS(vint8m2_t, int8_t, e8m2, 8) @@ -509,28 +507,6 @@ inline v_float64 v_lut(const double* tab, const v_int32& vidx) \ #endif -// Strangely, __riscv_vluxseg2ei32 is slower (tested on Muse-Pi and CanMV K230) -#define OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(_Tpvec, _Tp, suffix) \ -inline void v_lut_deinterleave(const _Tp* tab, const v_int32& vidx, _Tpvec& vx, _Tpvec& vy) \ -{ \ - v_uint32 vidx_ = __riscv_vmul(__riscv_vreinterpret_u32m2(vidx), sizeof(_Tp), VTraits::vlanes()); \ - vx = __riscv_vluxei32(tab, vidx_, VTraits<_Tpvec>::vlanes()); \ - vy = __riscv_vluxei32(tab, __riscv_vadd(vidx_, sizeof(_Tp), VTraits::vlanes()), VTraits<_Tpvec>::vlanes()); \ -} -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_float32, float, f32) -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_int32, int, i32) -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_uint32, unsigned, u32) - -#if CV_SIMD_SCALABLE_64F -inline void v_lut_deinterleave(const double* tab, const v_int32& vidx, v_float64& vx, v_float64& vy) \ -{ \ - vuint32m1_t vidx_ = __riscv_vmul(__riscv_vlmul_trunc_u32m1(__riscv_vreinterpret_u32m2(vidx)), sizeof(double), VTraits::vlanes()); \ - vx = __riscv_vluxei32(tab, vidx_, VTraits::vlanes()); \ - vy = __riscv_vluxei32(tab, __riscv_vadd(vidx_, sizeof(double), VTraits::vlanes()), VTraits::vlanes()); \ -} -#endif - - inline v_uint8 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); } inline v_uint8 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); } inline v_uint8 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); } @@ -1614,31 +1590,23 @@ OPENCV_HAL_IMPL_RVV_INTERLEAVED(int64, int64, i64, 64, 32, VTraits::vla OPENCV_HAL_IMPL_RVV_INTERLEAVED(float64, double, f64, 64, 32, VTraits::vlanes()) #endif -static std::array idx_interleave_pairs = { \ +static uint64_t idx_interleave_pairs[] = { \ 0x0705060403010200, 0x0f0d0e0c0b090a08, 0x1715161413111210, 0x1f1d1e1c1b191a18, \ 0x2725262423212220, 0x2f2d2e2c2b292a28, 0x3735363433313230, 0x3f3d3e3c3b393a38, \ 0x4745464443414240, 0x4f4d4e4c4b494a48, 0x5755565453515250, 0x5f5d5e5c5b595a58, \ - 0x6765666463616260, 0x6f6d6e6c6b696a68, 0x7775767473717270, 0x7f7d7e7c7b797a78, \ - 0x8785868483818280, 0x8f8d8e8c8b898a88, 0x9795969493919290, 0x9f9d9e9c9b999a98, \ - 0xa7a5a6a4a3a1a2a0, 0xafadaeacaba9aaa8, 0xb7b5b6b4b3b1b2b0, 0xbfbdbebcbbb9bab8, \ - 0xc7c5c6c4c3c1c2c0, 0xcfcdcecccbc9cac8, 0xd7d5d6d4d3d1d2d0, 0xdfdddedcdbd9dad8, \ - 0xe7e5e6e4e3e1e2e0, 0xefedeeecebe9eae8, 0xf7f5f6f4f3f1f2f0, 0xfffdfefcfbf9faf8}; + 0x6765666463616260, 0x6f6d6e6c6b696a68, 0x7775767473717270, 0x7f7d7e7c7b797a78}; -static std::array idx_interleave_quads = { \ +static uint64_t idx_interleave_quads[] = { \ 0x0703060205010400, 0x0f0b0e0a0d090c08, 0x1713161215111410, 0x1f1b1e1a1d191c18, \ 0x2723262225212420, 0x2f2b2e2a2d292c28, 0x3733363235313430, 0x3f3b3e3a3d393c38, \ 0x4743464245414440, 0x4f4b4e4a4d494c48, 0x5753565255515450, 0x5f5b5e5a5d595c58, \ - 0x6763666265616460, 0x6f6b6e6a6d696c68, 0x7773767275717470, 0x7f7b7e7a7d797c78, \ - 0x8783868285818480, 0x8f8b8e8a8d898c88, 0x9793969295919490, 0x9f9b9e9a9d999c98, \ - 0xa7a3a6a2a5a1a4a0, 0xafabaeaaada9aca8, 0xb7b3b6b2b5b1b4b0, 0xbfbbbebabdb9bcb8, \ - 0xc7c3c6c2c5c1c4c0, 0xcfcbcecacdc9ccc8, 0xd7d3d6d2d5d1d4d0, 0xdfdbdedaddd9dcd8, \ - 0xe7e3e6e2e5e1e4e0, 0xefebeeeaede9ece8, 0xf7f3f6f2f5f1f4f0, 0xfffbfefafdf9fcf8}; + 0x6763666265616460, 0x6f6b6e6a6d696c68, 0x7773767275717470, 0x7f7b7e7a7d797c78}; #define OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(_Tpvec, func) \ inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ vuint8m2_t vidx = __riscv_vundefined_u8m2();\ - vidx = __riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func.data(), idx_interleave_##func.size())); \ + vidx = __riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func, 16)); \ return __riscv_vrgather(vec, vidx, VTraits::vlanes()); \ } OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_uint8, pairs) @@ -1650,7 +1618,7 @@ OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_int8, quads) inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ vuint##width##m2_t vidx = __riscv_vundefined_u##width##m2();\ - vidx = __riscv_vget_u##width##m2(vzext_vfx(__riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func.data(), idx_interleave_##func.size())), VTraits::vlanes()), 0); \ + vidx = __riscv_vget_u##width##m2(vzext_vfx(__riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func, 16)), VTraits::vlanes()), 0); \ return __riscv_vrgather(vec, vidx, VTraits<_Tpvec>::vlanes()); \ } @@ -1722,19 +1690,20 @@ inline v_uint64 v_popcount(const v_uint64& a) inline v_uint8 v_popcount(const v_int8& a) { - return v_popcount(__riscv_vreinterpret_u8m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint16 v_popcount(const v_int16& a) { - return v_popcount(__riscv_vreinterpret_u16m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint32 v_popcount(const v_int32& a) { - return v_popcount(__riscv_vreinterpret_u32m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint64 v_popcount(const v_int64& a) { - return v_popcount(__riscv_vreinterpret_u64m2(a)); + // max(0 - a) is used, since v_abs does not support 64-bit integers. + return v_popcount(v_reinterpret_as_u64(__riscv_vmax(a, v_sub(v_setzero_s64(), a), VTraits::vlanes()))); } @@ -1828,14 +1797,14 @@ inline void v_pack_store(hfloat* ptr, const v_float32& v) #else inline v_float32 v_load_expand(const hfloat* ptr) { - float buf[VTraits::max_nlanes]; + float buf[32]; for( int i = 0; i < VTraits::vlanes(); i++ ) buf[i] = (float)ptr[i]; return v_load(buf); } inline void v_pack_store(hfloat* ptr, const v_float32& v) { - float buf[VTraits::max_nlanes]; + float buf[32]; v_store(buf, v); for( int i = 0; i < VTraits::vlanes(); i++ ) ptr[i] = hfloat(buf[i]); } @@ -2130,17 +2099,7 @@ inline v_int64 v_dotprod_expand_fast(const v_int16& a, const v_int16& b, const v // 32 >> 64f #if CV_SIMD_SCALABLE_64F inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b) -{ - vfloat64m1_t zero = __riscv_vfmv_v_f_f64m1(0, VTraits::vlanes()); - auto prod_i64 = __riscv_vwmul(a, b, VTraits::vlanes()); - // Convert to f64 before reduction to avoid overflow: #27003 - auto prod_f64 = __riscv_vfcvt_f(prod_i64, VTraits::vlanes()); - return __riscv_vset( // Needs v_float64 (vfloat64m2_t) here. - v_setall_f64(0.0f), // zero_f64m2 - 0, - __riscv_vfredusum_tu(zero, prod_f64, zero, VTraits::vlanes()) - ); -} +{ return v_cvt_f64(v_dotprod_fast(a, b)); } inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b, const v_float64& c) { return v_add(v_dotprod_expand_fast(a, b) , c); } #endif diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_vsx.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_vsx.hpp index 0a0915a22fc4ccdc80e5be5e9d8c33f01f468fa8..2157e1e87063e0e3b7a38d194130acf222360fb9 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_vsx.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/hal/intrin_vsx.hpp @@ -262,7 +262,7 @@ OPENCV_HAL_IMPL_VSX_EXTRACT_N(v_float64x2, double) inline _Tpvec v_setzero_##suffix() { return _Tpvec(vec_splats((_Tp)0)); } \ inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(vec_splats((_Tp)v));} \ template <> inline _Tpvec v_setzero_() { return v_setzero_##suffix(); } \ -template <> inline _Tpvec v_setall_(_Tp v) { return v_setall_##suffix(v); } \ +template <> inline _Tpvec v_setall_(_Tp v) { return v_setall_##suffix(_Tp v); } \ template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0 &a) \ { return _Tpvec((cast)a.val); } @@ -650,11 +650,11 @@ OPENCV_HAL_IMPL_VSX_SELECT(v_float64x2, vec_bdword2_c) #define OPENCV_HAL_IMPL_VSX_INT_CMP_OP(_Tpvec) \ inline _Tpvec v_eq(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpeq(a.val, b.val)); } \ -inline _Tpvec v_ne(const _Tpvec& a, const _Tpvec& b) \ +inline _Tpvec V_ne(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpne(a.val, b.val)); } \ inline _Tpvec v_lt(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmplt(a.val, b.val)); } \ -inline _Tpvec v_gt(const _Tpvec& a, const _Tpvec& b) \ +inline _Tpvec V_gt(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpgt(a.val, b.val)); } \ inline _Tpvec v_le(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmple(a.val, b.val)); } \ @@ -1507,7 +1507,7 @@ inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b, cons inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b) { return v_dotprod(a, b); } inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c) -{ return v_add(v_int32x4(vec_msum(a.val, b.val, vec_int4_z)), c); } +{ return v_int32x4(vec_msum(a.val, b.val, vec_int4_z)) + c; } // 32 >> 64 inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b) { return v_dotprod(a, b); } @@ -1518,7 +1518,7 @@ inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_ inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b) { return v_dotprod_expand(a, b); } inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c) -{ return v_add(v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)), c); } +{ return v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)) + c; } inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b) { diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.hpp index 4e86be7196e09ac8c5338decb82d88f79f269e60..2282e12aeef5204d9a2537aa051967cbc1648be9 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.hpp @@ -372,7 +372,6 @@ public: void release() const; void clear() const; void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const; - Mat reinterpret( int type ) const; void assign(const UMat& u) const; void assign(const Mat& m) const; @@ -1340,15 +1339,6 @@ public: */ Mat reshape(int cn, const std::vector& newshape) const; - /** @brief Reset the type of matrix. - - The methods reset the data type of matrix. If the new type and the old type of the matrix - have the same element size, the current buffer can be reused. The method needs to consider whether the - current mat is a submatrix or has any references. - @param type New data type. - */ - Mat reinterpret( int type ) const; - /** @brief Transposes a matrix. The method performs matrix transposition by means of matrix expressions. It does not perform the @@ -2482,8 +2472,8 @@ public: UMat(const UMat& m, const Range* ranges); UMat(const UMat& m, const std::vector& ranges); - //! builds matrix from std::vector. The data is always copied. The copyData - //! parameter is deprecated and will be removed in OpenCV 5.0. + // FIXIT copyData=false is not implemented, drop this in favor of cv::Mat (OpenCV 5.0) + //! builds matrix from std::vector with or without copying the data template explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); //! destructor - calls release() @@ -3566,7 +3556,7 @@ public: /** @brief Matrix expression representation @anchor MatrixExpressions This is a list of implemented matrix operations that can be combined in arbitrary complex -expressions (here A, B stand for matrices ( cv::Mat ), s for a cv::Scalar, alpha for a +expressions (here A, B stand for matrices ( Mat ), s for a scalar ( Scalar ), alpha for a real-valued scalar ( double )): - Addition, subtraction, negation: `A+B`, `A-B`, `A+s`, `A-s`, `s+A`, `s-A`, `-A` - Scaling: `A*alpha` @@ -3581,13 +3571,13 @@ real-valued scalar ( double )): 0. - Bitwise logical operations: `A logicop B`, `A logicop s`, `s logicop A`, `~A`, where *logicop* is one of `&`, `|`, `^`. -- Element-wise minimum and maximum: cv::min(A, B), cv::min(A, alpha), cv::max(A, B), cv::max(A, alpha) -- Element-wise absolute value: cv::abs(A) +- Element-wise minimum and maximum: `min(A, B)`, `min(A, alpha)`, `max(A, B)`, `max(A, alpha)` +- Element-wise absolute value: `abs(A)` - Cross-product, dot-product: `A.cross(B)`, `A.dot(B)` -- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as cv::norm, - cv::mean, cv::sum, cv::countNonZero, cv::trace, cv::determinant, cv::repeat, and others. +- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as norm, + mean, sum, countNonZero, trace, determinant, repeat, and others. - Matrix initializers ( Mat::eye(), Mat::zeros(), Mat::ones() ), matrix comma-separated - initializers, matrix constructors and operators that extract sub-matrices (see cv::Mat description). + initializers, matrix constructors and operators that extract sub-matrices (see Mat description). - Mat_() constructors to cast the result to the proper type. @note Comma-separated initializers and probably some other operations may require additional explicit Mat() or Mat_() constructor calls to resolve a possible ambiguity. diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.inl.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.inl.hpp index 8f904559d96523a0264b6accde46aad19450f4cb..bd0ba637b523c7d92ded4b87811f6efa6f0413a2 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.inl.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/mat.inl.hpp @@ -3024,12 +3024,6 @@ Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) return *this; } -template inline -MatExpr Mat_<_Tp>::zeros(int _ndims, const int* _sizes) -{ - return Mat::zeros(_ndims, _sizes, traits::Type<_Tp>::value); -} - template inline MatExpr Mat_<_Tp>::zeros(int rows, int cols) { @@ -3254,13 +3248,18 @@ const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) template inline UMat::UMat(const std::vector<_Tp>& vec, bool copyData) - : flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), - cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) +: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), +cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) { - CV_UNUSED(copyData); // parameter kept for backward compatibility if(vec.empty()) return; - Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this); + if( !copyData ) + { + // !!!TODO!!! + CV_Error(Error::StsNotImplemented, ""); + } + else + Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this); } inline diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/utils/logger.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/utils/logger.hpp index e5bf4551253fbb54f185b71bb67a2a0c14d16389..accb860ada8e3197f34e1226f1097784c8046ea2 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/utils/logger.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/utils/logger.hpp @@ -43,44 +43,6 @@ CV_EXPORTS void writeLogMessage(LogLevel logLevel, const char* message); /** Write log message */ CV_EXPORTS void writeLogMessageEx(LogLevel logLevel, const char* tag, const char* file, int line, const char* func, const char* message); -/** - * @brief Function pointer type for writeLogMessage. Used by replaceWriteLogMessage. - */ -typedef void (*WriteLogMessageFuncType)(LogLevel, const char*); - -/** - * @brief Function pointer type for writeLogMessageEx. Used by replaceWriteLogMessageEx. - */ -typedef void (*WriteLogMessageExFuncType)(LogLevel, const char*, const char*, int, const char*, const char*); - -/** - * @brief Replaces the OpenCV writeLogMessage function with a user-defined function. - * @note The user-defined function must have the same signature as writeLogMessage. - * @note The user-defined function must accept arguments that can be potentially null. - * @note The user-defined function must be thread-safe, as OpenCV logging may be called - * from multiple threads. - * @note The user-defined function must not perform any action that can trigger - * deadlocks or infinite loop. Many OpenCV functions are not re-entrant. - * @note Once replaced, logs will not go through the OpenCV writeLogMessage function. - * @note To restore, call this function with a nullptr. - */ -CV_EXPORTS void replaceWriteLogMessage(WriteLogMessageFuncType f); - -/** - * @brief Replaces the OpenCV writeLogMessageEx function with a user-defined function. - * @note The user-defined function must have the same signature as writeLogMessage. - * @note The user-defined function must accept arguments that can be potentially null. - * @note The user-defined function must be thread-safe, as OpenCV logging may be called - * from multiple threads. - * @note The user-defined function must not perform any action that can trigger - * deadlocks or infinite loop. Many OpenCV functions are not re-entrant. - * @note Once replaced, logs will not go through any of the OpenCV logging functions - * such as writeLogMessage or writeLogMessageEx, until their respective restore - * methods are called. - * @note To restore, call this function with a nullptr. - */ -CV_EXPORTS void replaceWriteLogMessageEx(WriteLogMessageExFuncType f); - } // namespace struct LogTagAuto diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/version.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/version.hpp index 690a61e3372da0457b2eff6db386a1d39830a573..7c5eaa14376865c42eed17ec9f25d3a6d0ffc1a3 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/version.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/version.hpp @@ -6,9 +6,9 @@ #define OPENCV_VERSION_HPP #define CV_VERSION_MAJOR 4 -#define CV_VERSION_MINOR 13 +#define CV_VERSION_MINOR 11 #define CV_VERSION_REVISION 0 -#define CV_VERSION_STATUS "-dev" +#define CV_VERSION_STATUS "" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/vsx_utils.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/vsx_utils.hpp index 4d5a694bae8e8fe1db7041c4a46fd94daed1e319..79a1074d59ff334fe083625b4537bcc018aa2af9 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/vsx_utils.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/core/vsx_utils.hpp @@ -257,8 +257,8 @@ VSX_IMPL_1VRG(vec_udword2, vec_udword2, vpopcntd, vec_popcntu) VSX_IMPL_1VRG(vec_udword2, vec_dword2, vpopcntd, vec_popcntu) // converts between single and double-precision -VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, vec_floate) -VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, vec_doubleo) +VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, __builtin_vsx_xvcvdpsp) +VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, __builtin_vsx_xvcvspdp) // converts word and doubleword to double-precision #undef vec_ctd @@ -399,6 +399,10 @@ VSX_REDIRECT_1RG(vec_ushort8, vec_ushort8, vec_popcntu, vec_popcnt) VSX_REDIRECT_1RG(vec_uint4, vec_uint4, vec_popcntu, vec_popcnt) VSX_REDIRECT_1RG(vec_udword2, vec_udword2, vec_popcntu, vec_popcnt) +// converts between single and double precision +VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, __builtin_vsx_xvcvdpsp) +VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, __builtin_vsx_xvcvspdp) + // converts word and doubleword to double-precision #ifdef vec_ctd # undef vec_ctd diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/cvconfig.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/cvconfig.h index 78290edcd31b158f63f4dd98ac7171a578bd9a1d..ad5233e70d9804bf14d6ca332816046c105d427c 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/cvconfig.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/cvconfig.h @@ -93,7 +93,7 @@ /* #undef HAVE_NVCUVENC */ /* OpenCL Support */ -/* #undef HAVE_OPENCL */ +#define HAVE_OPENCL /* #undef HAVE_OPENCL_STATIC */ /* #undef HAVE_OPENCL_SVM */ @@ -101,7 +101,7 @@ /* #undef HAVE_OPENCL_D3D11_NV */ /* OpenEXR codec */ -/* #undef HAVE_OPENEXR */ +#define HAVE_OPENEXR /* OpenGL support*/ /* #undef HAVE_OPENGL */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/dnn.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/dnn.hpp index fbe5044fef191fd66a7fd77fc8fa0c37936854a8..0077ae485389b2e2fbb50c85a7d65644b981400b 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/dnn.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/dnn.hpp @@ -72,7 +72,7 @@ CV__DNN_INLINE_NS_BEGIN //! DNN_BACKEND_DEFAULT equals to OPENCV_DNN_BACKEND_DEFAULT, which can be defined using CMake or a configuration parameter DNN_BACKEND_DEFAULT = 0, DNN_BACKEND_HALIDE, - DNN_BACKEND_INFERENCE_ENGINE, //!< Intel OpenVINO computational backend, supported targets: CPU, OPENCL, OPENCL_FP16, MYRIAD, HDDL, NPU + DNN_BACKEND_INFERENCE_ENGINE, //!< Intel OpenVINO computational backend //!< @note Tutorial how to build OpenCV with OpenVINO: @ref tutorial_dnn_openvino DNN_BACKEND_OPENCV, DNN_BACKEND_VKCOM, @@ -606,7 +606,7 @@ CV__DNN_INLINE_NS_BEGIN * * @returns index of bound layer (the same as layerId or newly created) */ - CV_WRAP int registerOutput(const std::string& outputName, int layerId, int outputPort); + int registerOutput(const std::string& outputName, int layerId, int outputPort); /** @brief Sets outputs names of the network input pseudo layer. * @@ -1219,16 +1219,16 @@ CV__DNN_INLINE_NS_BEGIN { CV_WRAP Image2BlobParams(); CV_WRAP Image2BlobParams(const Scalar& scalefactor, const Size& size = Size(), const Scalar& mean = Scalar(), - bool swapRB = false, int ddepth = CV_32F, dnn::DataLayout datalayout = DNN_LAYOUT_NCHW, - ImagePaddingMode mode = dnn::DNN_PMODE_NULL, Scalar borderValue = 0.0); + bool swapRB = false, int ddepth = CV_32F, DataLayout datalayout = DNN_LAYOUT_NCHW, + ImagePaddingMode mode = DNN_PMODE_NULL, Scalar borderValue = 0.0); CV_PROP_RW Scalar scalefactor; //!< scalefactor multiplier for input image values. CV_PROP_RW Size size; //!< Spatial size for output image. CV_PROP_RW Scalar mean; //!< Scalar with mean values which are subtracted from channels. CV_PROP_RW bool swapRB; //!< Flag which indicates that swap first and last channels CV_PROP_RW int ddepth; //!< Depth of output blob. Choose CV_32F or CV_8U. - CV_PROP_RW dnn::DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC. - CV_PROP_RW dnn::ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode. + CV_PROP_RW DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC. + CV_PROP_RW ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode. CV_PROP_RW Scalar borderValue; //!< Value used in padding mode for padding. /** @brief Get rectangle coordinates in original image system from rectangle in blob coordinates. diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/version.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/version.hpp index 8aa3177deb354b6b367cfffa6ef11c8289ad4616..5cf0870b444d70e94ea210ab32cfd01c80d6d797 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/version.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/dnn/version.hpp @@ -6,7 +6,7 @@ #define OPENCV_DNN_VERSION_HPP /// Use with major OpenCV version only. -#define OPENCV_DNN_API_VERSION 20250619 +#define OPENCV_DNN_API_VERSION 20241223 #if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS #define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION) diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/autotuned_index.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/autotuned_index.h index 0b02f5670a813704b3168c9ab215b6227c25e8e9..d90f739aff24da2c76159ccb531321191e65d1c1 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/autotuned_index.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/autotuned_index.h @@ -54,7 +54,7 @@ NNIndex* create_index_by_type(const Matrix #endif diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/kmeans_index.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/kmeans_index.h index 7ced99ca81e98276dd9d5717c9fad33db4bf3058..fd7fe2bd39f46092faa2595d8948a28b7ee560a8 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/kmeans_index.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/flann/kmeans_index.h @@ -62,7 +62,7 @@ struct KMeansIndexParams : public IndexParams { KMeansIndexParams(int branching = 32, int iterations = 11, flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, - float cb_index = 0.2f, int trees = 1 ) + float cb_index = 0.2, int trees = 1 ) { (*this)["algorithm"] = FLANN_INDEX_KMEANS; // branching factor diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2087641023c84821256e94ea2f74a3465c44c9a5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi.hpp @@ -0,0 +1,42 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_HPP +#define OPENCV_GAPI_HPP + +#include + +/** \defgroup gapi_ref G-API framework +@{ + @defgroup gapi_main_classes G-API Main Classes + @defgroup gapi_data_objects G-API Data Types + @{ + @defgroup gapi_meta_args G-API Metadata Descriptors + @} + @defgroup gapi_std_backends G-API Standard Backends + @defgroup gapi_compile_args G-API Graph Compilation Arguments + @defgroup gapi_serialization G-API Serialization functionality +@} + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Include these files here to avoid cyclic dependency between +// Desync & GKernel & GComputation & GStreamingCompiled. +#include +#include + +#endif // OPENCV_GAPI_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..60bb2c50745800bf02cf44a455453ee5119f1e44 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/core.hpp @@ -0,0 +1,1911 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_CORE_HPP +#define OPENCV_GAPI_CORE_HPP + +#include +#include // std::tuple + +#include +#include + +#include +#include +#include +#include + +/** \defgroup gapi_core G-API Core functionality +@{ + @defgroup gapi_math Graph API: Math operations + @defgroup gapi_pixelwise Graph API: Pixelwise operations + @defgroup gapi_matrixop Graph API: Operations on matrices + @defgroup gapi_transform Graph API: Image and channel composition functions +@} + */ + +namespace cv { namespace gapi { +/** + * @brief This namespace contains G-API Operation Types for OpenCV + * Core module functionality. + */ +namespace core { + using GResize = cv::gapi::imgproc::GResize; + using GResizeP = cv::gapi::imgproc::GResizeP; + + using GMat2 = std::tuple; + using GMat3 = std::tuple; // FIXME: how to avoid this? + using GMat4 = std::tuple; + using GMatScalar = std::tuple; + + G_TYPED_KERNEL(GAdd, , "org.opencv.core.math.add") { + static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) { + if (ddepth == -1) + { + // OpenCV: When the input arrays in add/subtract/multiply/divide + // functions have different depths, the output array depth must be + // explicitly specified! + // See artim_op() @ arithm.cpp + GAPI_Assert(a.chan == b.chan); + GAPI_Assert(a.depth == b.depth); + return a; + } + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GAddC, , "org.opencv.core.math.addC") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) { + GAPI_Assert(a.chan <= 4); + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GSub, , "org.opencv.core.math.sub") { + static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) { + if (ddepth == -1) + { + // This macro should select a larger data depth from a and b + // considering the number of channels in the same + // FIXME!!! Clarify if it is valid for sub() + GAPI_Assert(a.chan == b.chan); + ddepth = std::max(a.depth, b.depth); + } + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GSubC, , "org.opencv.core.math.subC") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) { + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GSubRC,, "org.opencv.core.math.subRC") { + static GMatDesc outMeta(GScalarDesc, GMatDesc b, int ddepth) { + return b.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GMul, , "org.opencv.core.math.mul") { + static GMatDesc outMeta(GMatDesc a, GMatDesc, double, int ddepth) { + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GMulCOld, , "org.opencv.core.math.mulCOld") { + static GMatDesc outMeta(GMatDesc a, double, int ddepth) { + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GMulC, , "org.opencv.core.math.mulC") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) { + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GMulS, , "org.opencv.core.math.muls") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a; + } + }; // FIXME: Merge with MulC + + G_TYPED_KERNEL(GDiv, , "org.opencv.core.math.div") { + static GMatDesc outMeta(GMatDesc a, GMatDesc b, double, int ddepth) { + if (ddepth == -1) + { + GAPI_Assert(a.depth == b.depth); + return b; + } + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GDivC, , "org.opencv.core.math.divC") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc, double, int ddepth) { + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GDivRC, , "org.opencv.core.math.divRC") { + static GMatDesc outMeta(GScalarDesc, GMatDesc b, double, int ddepth) { + return b.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GMean, , "org.opencv.core.math.mean") { + static GScalarDesc outMeta(GMatDesc) { + return empty_scalar_desc(); + } + }; + + G_TYPED_KERNEL_M(GPolarToCart, , "org.opencv.core.math.polarToCart") { + static std::tuple outMeta(GMatDesc, GMatDesc a, bool) { + return std::make_tuple(a, a); + } + }; + + G_TYPED_KERNEL_M(GCartToPolar, , "org.opencv.core.math.cartToPolar") { + static std::tuple outMeta(GMatDesc x, GMatDesc, bool) { + return std::make_tuple(x, x); + } + }; + + G_TYPED_KERNEL(GPhase, , "org.opencv.core.math.phase") { + static GMatDesc outMeta(const GMatDesc &inx, const GMatDesc &, bool) { + return inx; + } + }; + + G_TYPED_KERNEL(GMask, , "org.opencv.core.pixelwise.mask") { + static GMatDesc outMeta(GMatDesc in, GMatDesc) { + return in; + } + }; + + G_TYPED_KERNEL(GCmpGT, , "org.opencv.core.pixelwise.compare.cmpGT") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpGE, , "org.opencv.core.pixelwise.compare.cmpGE") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpLE, , "org.opencv.core.pixelwise.compare.cmpLE") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpLT, , "org.opencv.core.pixelwise.compare.cmpLT") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpEQ, , "org.opencv.core.pixelwise.compare.cmpEQ") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpNE, , "org.opencv.core.pixelwise.compare.cmpNE") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpGTScalar, , "org.opencv.core.pixelwise.compare.cmpGTScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpGEScalar, , "org.opencv.core.pixelwise.compare.cmpGEScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpLEScalar, , "org.opencv.core.pixelwise.compare.cmpLEScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpLTScalar, , "org.opencv.core.pixelwise.compare.cmpLTScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpEQScalar, , "org.opencv.core.pixelwise.compare.cmpEQScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GCmpNEScalar, , "org.opencv.core.pixelwise.compare.cmpNEScalar") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a.withDepth(CV_8U); + } + }; + + G_TYPED_KERNEL(GAnd, , "org.opencv.core.pixelwise.bitwise_and") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GAndS, , "org.opencv.core.pixelwise.bitwise_andS") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GOr, , "org.opencv.core.pixelwise.bitwise_or") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GOrS, , "org.opencv.core.pixelwise.bitwise_orS") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GXor, , "org.opencv.core.pixelwise.bitwise_xor") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GXorS, , "org.opencv.core.pixelwise.bitwise_xorS") { + static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GNot, , "org.opencv.core.pixelwise.bitwise_not") { + static GMatDesc outMeta(GMatDesc a) { + return a; + } + }; + + G_TYPED_KERNEL(GSelect, , "org.opencv.core.pixelwise.select") { + static GMatDesc outMeta(GMatDesc a, GMatDesc, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GMin, , "org.opencv.core.matrixop.min") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GMax, , "org.opencv.core.matrixop.max") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GAbsDiff, , "org.opencv.core.matrixop.absdiff") { + static GMatDesc outMeta(GMatDesc a, GMatDesc) { + return a; + } + }; + + G_TYPED_KERNEL(GAbsDiffC, , "org.opencv.core.matrixop.absdiffC") { + static GMatDesc outMeta(const GMatDesc& a, const GScalarDesc&) { + return a; + } + }; + + G_TYPED_KERNEL(GSum, , "org.opencv.core.matrixop.sum") { + static GScalarDesc outMeta(GMatDesc) { + return empty_scalar_desc(); + } + }; + + G_TYPED_KERNEL(GCountNonZero, (GMat)>, "org.opencv.core.matrixop.countNonZero") { + static GOpaqueDesc outMeta(GMatDesc in) { + GAPI_Assert(in.chan == 1); + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GAddW, , "org.opencv.core.matrixop.addweighted") { + static GMatDesc outMeta(GMatDesc a, double, GMatDesc b, double, double, int ddepth) { + if (ddepth == -1) + { + // OpenCV: When the input arrays in add/subtract/multiply/divide + // functions have different depths, the output array depth must be + // explicitly specified! + // See artim_op() @ arithm.cpp + GAPI_Assert(a.chan == b.chan); + GAPI_Assert(a.depth == b.depth); + return a; + } + return a.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GNormL1, , "org.opencv.core.matrixop.norml1") { + static GScalarDesc outMeta(GMatDesc) { + return empty_scalar_desc(); + } + }; + + G_TYPED_KERNEL(GNormL2, , "org.opencv.core.matrixop.norml2") { + static GScalarDesc outMeta(GMatDesc) { + return empty_scalar_desc(); + } + }; + + G_TYPED_KERNEL(GNormInf, , "org.opencv.core.matrixop.norminf") { + static GScalarDesc outMeta(GMatDesc) { + return empty_scalar_desc(); + } + }; + + G_TYPED_KERNEL_M(GIntegral, , "org.opencv.core.matrixop.integral") { + static std::tuple outMeta(GMatDesc in, int sd, int sqd) { + return std::make_tuple(in.withSizeDelta(1,1).withDepth(sd), + in.withSizeDelta(1,1).withDepth(sqd)); + } + }; + + G_TYPED_KERNEL(GThreshold, , "org.opencv.core.matrixop.threshold") { + static GMatDesc outMeta(GMatDesc in, GScalarDesc, GScalarDesc, int) { + return in; + } + }; + + + G_TYPED_KERNEL_M(GThresholdOT, , "org.opencv.core.matrixop.thresholdOT") { + static std::tuple outMeta(GMatDesc in, GScalarDesc, int) { + return std::make_tuple(in, empty_scalar_desc()); + } + }; + + G_TYPED_KERNEL(GInRange, , "org.opencv.core.matrixop.inrange") { + static GMatDesc outMeta(GMatDesc in, GScalarDesc, GScalarDesc) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL_M(GSplit3, , "org.opencv.core.transform.split3") { + static std::tuple outMeta(GMatDesc in) { + const auto out_depth = in.depth; + const auto out_desc = in.withType(out_depth, 1); + return std::make_tuple(out_desc, out_desc, out_desc); + } + }; + + G_TYPED_KERNEL_M(GSplit4, ,"org.opencv.core.transform.split4") { + static std::tuple outMeta(GMatDesc in) { + const auto out_depth = in.depth; + const auto out_desc = in.withType(out_depth, 1); + return std::make_tuple(out_desc, out_desc, out_desc, out_desc); + } + }; + + G_TYPED_KERNEL(GMerge3, , "org.opencv.core.transform.merge3") { + static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc) { + // Preserve depth and add channel component + return in.withType(in.depth, 3); + } + }; + + G_TYPED_KERNEL(GMerge4, , "org.opencv.core.transform.merge4") { + static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc, GMatDesc) { + // Preserve depth and add channel component + return in.withType(in.depth, 4); + } + }; + + G_TYPED_KERNEL(GRemap, , "org.opencv.core.transform.remap") { + static GMatDesc outMeta(GMatDesc in, Mat m1, Mat, int, int, Scalar) { + return in.withSize(m1.size()); + } + }; + + G_TYPED_KERNEL(GFlip, , "org.opencv.core.transform.flip") { + static GMatDesc outMeta(GMatDesc in, int) { + return in; + } + }; + + // TODO: eliminate the need in this kernel (streaming) + G_TYPED_KERNEL(GCrop, , "org.opencv.core.transform.crop") { + static GMatDesc outMeta(GMatDesc in, Rect rc) { + return in.withSize(Size(rc.width, rc.height)); + } + }; + + G_TYPED_KERNEL(GConcatHor, , "org.opencv.imgproc.transform.concatHor") { + static GMatDesc outMeta(GMatDesc l, GMatDesc r) { + return l.withSizeDelta(+r.size.width, 0); + } + }; + + G_TYPED_KERNEL(GConcatVert, , "org.opencv.imgproc.transform.concatVert") { + static GMatDesc outMeta(GMatDesc t, GMatDesc b) { + return t.withSizeDelta(0, +b.size.height); + } + }; + + G_TYPED_KERNEL(GLUT, , "org.opencv.core.transform.LUT") { + static GMatDesc outMeta(GMatDesc in, Mat) { + return in; + } + }; + + G_TYPED_KERNEL(GConvertTo, , "org.opencv.core.transform.convertTo") { + static GMatDesc outMeta(GMatDesc in, int rdepth, double, double) { + return rdepth < 0 ? in : in.withDepth(rdepth); + } + }; + + G_TYPED_KERNEL(GSqrt, , "org.opencv.core.math.sqrt") { + static GMatDesc outMeta(GMatDesc in) { + return in; + } + }; + + G_TYPED_KERNEL(GNormalize, , "org.opencv.core.normalize") { + static GMatDesc outMeta(GMatDesc in, double, double, int, int ddepth) { + // unlike opencv doesn't have a mask as a parameter + return (ddepth < 0 ? in : in.withDepth(ddepth)); + } + }; + + G_TYPED_KERNEL(GWarpPerspective, , "org.opencv.core.warpPerspective") { + static GMatDesc outMeta(GMatDesc in, const Mat&, Size dsize, int, int borderMode, const cv::Scalar&) { + GAPI_Assert((borderMode == cv::BORDER_CONSTANT || borderMode == cv::BORDER_REPLICATE) && + "cv::gapi::warpPerspective supports only cv::BORDER_CONSTANT and cv::BORDER_REPLICATE border modes"); + return in.withType(in.depth, in.chan).withSize(dsize); + } + }; + + G_TYPED_KERNEL(GWarpAffine, , "org.opencv.core.warpAffine") { + static GMatDesc outMeta(GMatDesc in, const Mat&, Size dsize, int, int border_mode, const cv::Scalar&) { + GAPI_Assert(border_mode != cv::BORDER_TRANSPARENT && + "cv::BORDER_TRANSPARENT mode is not supported in cv::gapi::warpAffine"); + return in.withType(in.depth, in.chan).withSize(dsize); + } + }; + + G_TYPED_KERNEL( + GKMeansND, + ,GMat,GMat>(GMat,int,GMat,TermCriteria,int,KmeansFlags)>, + "org.opencv.core.kmeansND") { + + static std::tuple + outMeta(const GMatDesc& in, int K, const GMatDesc& bestLabels, const TermCriteria&, int, + KmeansFlags flags) { + GAPI_Assert(in.depth == CV_32F); + std::vector amount_n_dim = detail::checkVector(in); + int amount = amount_n_dim[0], dim = amount_n_dim[1]; + if (amount == -1) // Mat with height != 1, width != 1, channels != 1 given + { // which means that kmeans will consider the following: + amount = in.size.height; + dim = in.size.width * in.chan; + } + // kmeans sets these labels' sizes when no bestLabels given: + GMatDesc out_labels(CV_32S, 1, Size{1, amount}); + // kmeans always sets these centers' sizes: + GMatDesc centers (CV_32F, 1, Size{dim, K}); + if (flags & KMEANS_USE_INITIAL_LABELS) + { + GAPI_Assert(bestLabels.depth == CV_32S); + int labels_amount = detail::checkVector(bestLabels, 1u); + GAPI_Assert(labels_amount == amount); + out_labels = bestLabels; // kmeans preserves bestLabels' sizes if given + } + return std::make_tuple(empty_gopaque_desc(), out_labels, centers); + } + }; + + G_TYPED_KERNEL( + GKMeansNDNoInit, + ,GMat,GMat>(GMat,int,TermCriteria,int,KmeansFlags)>, + "org.opencv.core.kmeansNDNoInit") { + + static std::tuple + outMeta(const GMatDesc& in, int K, const TermCriteria&, int, KmeansFlags flags) { + GAPI_Assert( !(flags & KMEANS_USE_INITIAL_LABELS) ); + GAPI_Assert(in.depth == CV_32F); + std::vector amount_n_dim = detail::checkVector(in); + int amount = amount_n_dim[0], dim = amount_n_dim[1]; + if (amount == -1) // Mat with height != 1, width != 1, channels != 1 given + { // which means that kmeans will consider the following: + amount = in.size.height; + dim = in.size.width * in.chan; + } + GMatDesc out_labels(CV_32S, 1, Size{1, amount}); + GMatDesc centers (CV_32F, 1, Size{dim, K}); + return std::make_tuple(empty_gopaque_desc(), out_labels, centers); + } + }; + + G_TYPED_KERNEL(GKMeans2D, ,GArray,GArray> + (GArray,int,GArray,TermCriteria,int,KmeansFlags)>, + "org.opencv.core.kmeans2D") { + static std::tuple + outMeta(const GArrayDesc&,int,const GArrayDesc&,const TermCriteria&,int,KmeansFlags) { + return std::make_tuple(empty_gopaque_desc(), empty_array_desc(), empty_array_desc()); + } + }; + + G_TYPED_KERNEL(GKMeans3D, ,GArray,GArray> + (GArray,int,GArray,TermCriteria,int,KmeansFlags)>, + "org.opencv.core.kmeans3D") { + static std::tuple + outMeta(const GArrayDesc&,int,const GArrayDesc&,const TermCriteria&,int,KmeansFlags) { + return std::make_tuple(empty_gopaque_desc(), empty_array_desc(), empty_array_desc()); + } + }; + + G_TYPED_KERNEL(GTranspose, , "org.opencv.core.transpose") { + static GMatDesc outMeta(GMatDesc in) { + return in.withSize({in.size.height, in.size.width}); + } + }; +} // namespace core + +namespace streaming { + +// Operations for Streaming (declared in this header for convenience) +G_TYPED_KERNEL(GSize, (GMat)>, "org.opencv.streaming.size") { + static GOpaqueDesc outMeta(const GMatDesc&) { + return empty_gopaque_desc(); + } +}; + +G_TYPED_KERNEL(GSizeR, (GOpaque)>, "org.opencv.streaming.sizeR") { + static GOpaqueDesc outMeta(const GOpaqueDesc&) { + return empty_gopaque_desc(); + } +}; + +G_TYPED_KERNEL(GSizeMF, (GFrame)>, "org.opencv.streaming.sizeMF") { + static GOpaqueDesc outMeta(const GFrameDesc&) { + return empty_gopaque_desc(); + } +}; +} // namespace streaming + +//! @addtogroup gapi_math +//! @{ + +/** @brief Calculates the per-element sum of two matrices. + +The function add calculates sum of two matrices of the same size and the same number of channels: +\f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2}(I)) \quad \texttt{if mask}(I) \ne0\f] + +The function can be replaced with matrix expressions: + \f[\texttt{dst} = \texttt{src1} + \texttt{src2}\f] + +The input matrices and the output matrix can all have the same or different depths. For example, you +can add a 16-bit unsigned matrix to a 8-bit signed matrix and store the sum as a 32-bit +floating-point matrix. Depth of the output matrix is determined by the ddepth parameter. +If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have +the same depth as the input matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.add" +@param src1 first input matrix. +@param src2 second input matrix. +@param ddepth optional depth of the output matrix. +@sa sub, addWeighted +*/ +GAPI_EXPORTS_W GMat add(const GMat& src1, const GMat& src2, int ddepth = -1); + +/** @brief Calculates the per-element sum of matrix and given scalar. + +The function addC adds a given scalar value to each element of given matrix. +The function can be replaced with matrix expressions: + + \f[\texttt{dst} = \texttt{src1} + \texttt{c}\f] + +Depth of the output matrix is determined by the ddepth parameter. +If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix. +The matrices can be single or multi channel. Output matrix must have the same size and number of channels as the input matrix. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.addC" +@param src1 first input matrix. +@param c scalar value to be added. +@param ddepth optional depth of the output matrix. +@sa sub, addWeighted +*/ +GAPI_EXPORTS_W GMat addC(const GMat& src1, const GScalar& c, int ddepth = -1); +//! @overload +GAPI_EXPORTS_W GMat addC(const GScalar& c, const GMat& src1, int ddepth = -1); + +/** @brief Calculates the per-element difference between two matrices. + +The function sub calculates difference between two matrices, when both matrices have the same size and the same number of +channels: + \f[\texttt{dst}(I) = \texttt{src1}(I) - \texttt{src2}(I)\f] + +The function can be replaced with matrix expressions: +\f[\texttt{dst} = \texttt{src1} - \texttt{src2}\f] + +The input matrices and the output matrix can all have the same or different depths. For example, you +can subtract two 8-bit unsigned matrices store the result as a 16-bit signed matrix. +Depth of the output matrix is determined by the ddepth parameter. +If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have +the same depth as the input matrices. The matrices can be single or multi channel. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.sub" +@param src1 first input matrix. +@param src2 second input matrix. +@param ddepth optional depth of the output matrix. +@sa add, addC + */ +GAPI_EXPORTS_W GMat sub(const GMat& src1, const GMat& src2, int ddepth = -1); + +/** @brief Calculates the per-element difference between matrix and given scalar. + +The function can be replaced with matrix expressions: + \f[\texttt{dst} = \texttt{src} - \texttt{c}\f] + +Depth of the output matrix is determined by the ddepth parameter. +If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix. +The matrices can be single or multi channel. Output matrix must have the same size as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.subC" +@param src first input matrix. +@param c scalar value to subtracted. +@param ddepth optional depth of the output matrix. +@sa add, addC, subRC + */ +GAPI_EXPORTS_W GMat subC(const GMat& src, const GScalar& c, int ddepth = -1); + +/** @brief Calculates the per-element difference between given scalar and the matrix. + +The function can be replaced with matrix expressions: + \f[\texttt{dst} = \texttt{c} - \texttt{src}\f] + +Depth of the output matrix is determined by the ddepth parameter. +If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix. +The matrices can be single or multi channel. Output matrix must have the same size as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.subRC" +@param c scalar value to subtract from. +@param src input matrix to be subtracted. +@param ddepth optional depth of the output matrix. +@sa add, addC, subC + */ +GAPI_EXPORTS_W GMat subRC(const GScalar& c, const GMat& src, int ddepth = -1); + +/** @brief Calculates the per-element scaled product of two matrices. + +The function mul calculates the per-element product of two matrices: + +\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{scale} \cdot \texttt{src1} (I) \cdot \texttt{src2} (I))\f] + +If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have +the same depth as the input matrices. The matrices can be single or multi channel. +Output matrix must have the same size as input matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.mul" +@param src1 first input matrix. +@param src2 second input matrix of the same size and the same depth as src1. +@param scale optional scale factor. +@param ddepth optional depth of the output matrix. +@sa add, sub, div, addWeighted +*/ +GAPI_EXPORTS_W GMat mul(const GMat& src1, const GMat& src2, double scale = 1.0, int ddepth = -1); + +/** @brief Multiplies matrix by scalar. + +The function mulC multiplies each element of matrix src by given scalar value: + +\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I) \cdot \texttt{multiplier} )\f] + +The matrices can be single or multi channel. Output matrix must have the same size as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.mulC" +@param src input matrix. +@param multiplier factor to be multiplied. +@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth. +@sa add, sub, div, addWeighted +*/ +GAPI_EXPORTS_W GMat mulC(const GMat& src, double multiplier, int ddepth = -1); +//! @overload +GAPI_EXPORTS_W GMat mulC(const GMat& src, const GScalar& multiplier, int ddepth = -1); // FIXME: merge with mulc +//! @overload +GAPI_EXPORTS_W GMat mulC(const GScalar& multiplier, const GMat& src, int ddepth = -1); // FIXME: merge with mulc + +/** @brief Performs per-element division of two matrices. + +The function divides one matrix by another: +\f[\texttt{dst(I) = saturate(src1(I)*scale/src2(I))}\f] + +For integer types when src2(I) is zero, dst(I) will also be zero. +Floating point case returns Inf/NaN (according to IEEE). + +Different channels of +multi-channel matrices are processed independently. +The matrices can be single or multi channel. Output matrix must have the same size and depth as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.div" +@param src1 first input matrix. +@param src2 second input matrix of the same size and depth as src1. +@param scale scalar factor. +@param ddepth optional depth of the output matrix; you can only pass -1 when src1.depth() == src2.depth(). +@sa mul, add, sub +*/ +GAPI_EXPORTS_W GMat div(const GMat& src1, const GMat& src2, double scale, int ddepth = -1); + +/** @brief Divides matrix by scalar. + +The function divC divides each element of matrix src by given scalar value: + +\f[\texttt{dst(I) = saturate(src(I)*scale/divisor)}\f] + +When divisor is zero, dst(I) will also be zero. Different channels of +multi-channel matrices are processed independently. +The matrices can be single or multi channel. Output matrix must have the same size and depth as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.divC" +@param src input matrix. +@param divisor number to be divided by. +@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth. +@param scale scale factor. +@sa add, sub, div, addWeighted +*/ +GAPI_EXPORTS_W GMat divC(const GMat& src, const GScalar& divisor, double scale, int ddepth = -1); + +/** @brief Divides scalar by matrix. + +The function divRC divides given scalar by each element of matrix src and keep the division result in new matrix of the same size and type as src: + +\f[\texttt{dst(I) = saturate(divident*scale/src(I))}\f] + +When src(I) is zero, dst(I) will also be zero. Different channels of +multi-channel matrices are processed independently. +The matrices can be single or multi channel. Output matrix must have the same size and depth as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.divRC" +@param src input matrix. +@param divident number to be divided. +@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth. +@param scale scale factor +@sa add, sub, div, addWeighted +*/ +GAPI_EXPORTS_W GMat divRC(const GScalar& divident, const GMat& src, double scale, int ddepth = -1); + +/** @brief Applies a mask to a matrix. + +The function mask set value from given matrix if the corresponding pixel value in mask matrix set to true, +and set the matrix value to 0 otherwise. + +Supported src matrix data types are @ref CV_8UC1, @ref CV_16SC1, @ref CV_16UC1. Supported mask data type is @ref CV_8UC1. + +@note Function textual ID is "org.opencv.core.math.mask" +@param src input matrix. +@param mask input mask matrix. +*/ +GAPI_EXPORTS_W GMat mask(const GMat& src, const GMat& mask); + +/** @brief Calculates an average (mean) of matrix elements. + +The function mean calculates the mean value M of matrix elements, +independently for each channel, and return it. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.math.mean" +@param src input matrix. +@sa countNonZero, min, max +*/ +GAPI_EXPORTS_W GScalar mean(const GMat& src); + +/** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle. + +The function polarToCart calculates the Cartesian coordinates of each 2D +vector represented by the corresponding elements of magnitude and angle: +\f[\begin{array}{l} \texttt{x} (I) = \texttt{magnitude} (I) \cos ( \texttt{angle} (I)) \\ \texttt{y} (I) = \texttt{magnitude} (I) \sin ( \texttt{angle} (I)) \\ \end{array}\f] + +The relative accuracy of the estimated coordinates is about 1e-6. + +First output is a matrix of x-coordinates of 2D vectors. +Second output is a matrix of y-coordinates of 2D vectors. +Both output must have the same size and depth as input matrices. + +@note Function textual ID is "org.opencv.core.math.polarToCart" + +@param magnitude input floating-point @ref CV_32FC1 matrix (1xN) of magnitudes of 2D vectors; +@param angle input floating-point @ref CV_32FC1 matrix (1xN) of angles of 2D vectors. +@param angleInDegrees when true, the input angles are measured in +degrees, otherwise, they are measured in radians. +@sa cartToPolar, exp, log, pow, sqrt +*/ +GAPI_EXPORTS_W std::tuple polarToCart(const GMat& magnitude, const GMat& angle, + bool angleInDegrees = false); + +/** @brief Calculates the magnitude and angle of 2D vectors. + +The function cartToPolar calculates either the magnitude, angle, or both +for every 2D vector (x(I),y(I)): +\f[\begin{array}{l} \texttt{magnitude} (I)= \sqrt{\texttt{x}(I)^2+\texttt{y}(I)^2} , \\ \texttt{angle} (I)= \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))[ \cdot180 / \pi ] \end{array}\f] + +The angles are calculated with accuracy about 0.3 degrees. For the point +(0,0), the angle is set to 0. + +First output is a matrix of magnitudes of the same size and depth as input x. +Second output is a matrix of angles that has the same size and depth as +x; the angles are measured in radians (from 0 to 2\*Pi) or in degrees (0 to 360 degrees). + +@note Function textual ID is "org.opencv.core.math.cartToPolar" + +@param x matrix of @ref CV_32FC1 x-coordinates. +@param y array of @ref CV_32FC1 y-coordinates. +@param angleInDegrees a flag, indicating whether the angles are measured +in radians (which is by default), or in degrees. +@sa polarToCart +*/ +GAPI_EXPORTS_W std::tuple cartToPolar(const GMat& x, const GMat& y, + bool angleInDegrees = false); + +/** @brief Calculates the rotation angle of 2D vectors. + +The function cv::phase calculates the rotation angle of each 2D vector that +is formed from the corresponding elements of x and y : +\f[\texttt{angle} (I) = \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))\f] + +The angle estimation accuracy is about 0.3 degrees. When x(I)=y(I)=0 , +the corresponding angle(I) is set to 0. +@param x input floating-point array of x-coordinates of 2D vectors. +@param y input array of y-coordinates of 2D vectors; it must have the +same size and the same type as x. +@param angleInDegrees when true, the function calculates the angle in +degrees, otherwise, they are measured in radians. +@return array of vector angles; it has the same size and same type as x. +*/ +GAPI_EXPORTS_W GMat phase(const GMat& x, const GMat &y, bool angleInDegrees = false); + +/** @brief Calculates a square root of array elements. + +The function cv::gapi::sqrt calculates a square root of each input array element. +In case of multi-channel arrays, each channel is processed +independently. The accuracy is approximately the same as of the built-in +std::sqrt . +@param src input floating-point array. +@return output array of the same size and type as src. +*/ +GAPI_EXPORTS_W GMat sqrt(const GMat &src); + +//! @} gapi_math +//! +//! @addtogroup gapi_pixelwise +//! @{ + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are greater compare to elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) > \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: +\f[\texttt{dst} = \texttt{src1} > \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices/matrix. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGT" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpLE, cmpGE, cmpLT +*/ +GAPI_EXPORTS_W GMat cmpGT(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGTScalar" +*/ +GAPI_EXPORTS_W GMat cmpGT(const GMat& src1, const GScalar& src2); + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are less than elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) < \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: + \f[\texttt{dst} = \texttt{src1} < \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices/matrix. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLT" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpLE, cmpGE, cmpGT +*/ +GAPI_EXPORTS_W GMat cmpLT(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLTScalar" +*/ +GAPI_EXPORTS_W GMat cmpLT(const GMat& src1, const GScalar& src2); + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are greater or equal compare to elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) >= \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: + \f[\texttt{dst} = \texttt{src1} >= \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGE" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpLE, cmpGT, cmpLT +*/ +GAPI_EXPORTS_W GMat cmpGE(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLGEcalar" +*/ +GAPI_EXPORTS_W GMat cmpGE(const GMat& src1, const GScalar& src2); + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are less or equal compare to elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) <= \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: + \f[\texttt{dst} = \texttt{src1} <= \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLE" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpGT, cmpGE, cmpLT +*/ +GAPI_EXPORTS_W GMat cmpLE(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLEScalar" +*/ +GAPI_EXPORTS_W GMat cmpLE(const GMat& src1, const GScalar& src2); + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are equal to elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) == \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: + \f[\texttt{dst} = \texttt{src1} == \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpEQ" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpNE +*/ +GAPI_EXPORTS_W GMat cmpEQ(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpEQScalar" +*/ +GAPI_EXPORTS_W GMat cmpEQ(const GMat& src1, const GScalar& src2); + +/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are not equal to elements in second. + +The function compares elements of two matrices src1 and src2 of the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) != \texttt{src2} (I)\f] + +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: + \f[\texttt{dst} = \texttt{src1} != \texttt{src2}\f] + +Output matrix of depth @ref CV_8U must have the same size and the same number of channels as + the input matrices. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpNE" +@param src1 first input matrix. +@param src2 second input matrix/scalar of the same depth as first input matrix. +@sa min, max, threshold, cmpEQ +*/ +GAPI_EXPORTS_W GMat cmpNE(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpNEScalar" +*/ +GAPI_EXPORTS_W GMat cmpNE(const GMat& src1, const GScalar& src2); + +/** @brief computes bitwise conjunction of the two matrixes (src1 & src2) +Calculates the per-element bit-wise logical conjunction of two matrices of the same size. + +In case of floating-point matrices, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel matrices, each channel is processed +independently. Output matrix must have the same size and depth as the input +matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_and" + +@param src1 first input matrix. +@param src2 second input matrix. +*/ +GAPI_EXPORTS_W GMat bitwise_and(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_andS" +@param src1 first input matrix. +@param src2 scalar, which will be per-lemenetly conjuncted with elements of src1. +*/ +GAPI_EXPORTS_W GMat bitwise_and(const GMat& src1, const GScalar& src2); + +/** @brief computes bitwise disjunction of the two matrixes (src1 | src2) +Calculates the per-element bit-wise logical disjunction of two matrices of the same size. + +In case of floating-point matrices, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel matrices, each channel is processed +independently. Output matrix must have the same size and depth as the input +matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_or" + +@param src1 first input matrix. +@param src2 second input matrix. +*/ +GAPI_EXPORTS_W GMat bitwise_or(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_orS" +@param src1 first input matrix. +@param src2 scalar, which will be per-lemenetly disjuncted with elements of src1. +*/ +GAPI_EXPORTS_W GMat bitwise_or(const GMat& src1, const GScalar& src2); + + +/** @brief computes bitwise logical "exclusive or" of the two matrixes (src1 ^ src2) +Calculates the per-element bit-wise logical "exclusive or" of two matrices of the same size. + +In case of floating-point matrices, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel matrices, each channel is processed +independently. Output matrix must have the same size and depth as the input +matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_xor" + +@param src1 first input matrix. +@param src2 second input matrix. +*/ +GAPI_EXPORTS_W GMat bitwise_xor(const GMat& src1, const GMat& src2); +/** @overload +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_xorS" +@param src1 first input matrix. +@param src2 scalar, for which per-lemenet "logical or" operation on elements of src1 will be performed. +*/ +GAPI_EXPORTS_W GMat bitwise_xor(const GMat& src1, const GScalar& src2); + + +/** @brief Inverts every bit of an array. + +The function bitwise_not calculates per-element bit-wise inversion of the input +matrix: +\f[\texttt{dst} (I) = \neg \texttt{src} (I)\f] + +In case of floating-point matrices, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel matrices, each channel is processed +independently. Output matrix must have the same size and depth as the input +matrix. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.bitwise_not" + +@param src input matrix. +*/ +GAPI_EXPORTS_W GMat bitwise_not(const GMat& src); + +/** @brief Select values from either first or second of input matrices by given mask. +The function set to the output matrix either the value from the first input matrix if corresponding value of mask matrix is 255, + or value from the second input matrix (if value of mask matrix set to 0). + +Input mask matrix must be of @ref CV_8UC1 type, two other inout matrices and output matrix should be of the same type. The size should +be the same for all input and output matrices. +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.pixelwise.select" + +@param src1 first input matrix. +@param src2 second input matrix. +@param mask mask input matrix. +*/ +GAPI_EXPORTS_W GMat select(const GMat& src1, const GMat& src2, const GMat& mask); + +//! @} gapi_pixelwise + + +//! @addtogroup gapi_matrixop +//! @{ +/** @brief Calculates per-element minimum of two matrices. + +The function min calculates the per-element minimum of two matrices of the same size, number of channels and depth: +\f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{src2} (I))\f] + where I is a multi-dimensional index of matrix elements. In case of + multi-channel matrices, each channel is processed independently. +Output matrix must be of the same size and depth as src1. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.min" +@param src1 first input matrix. +@param src2 second input matrix of the same size and depth as src1. +@sa max, cmpEQ, cmpLT, cmpLE +*/ +GAPI_EXPORTS_W GMat min(const GMat& src1, const GMat& src2); + +/** @brief Calculates per-element maximum of two matrices. + +The function max calculates the per-element maximum of two matrices of the same size, number of channels and depth: +\f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{src2} (I))\f] + where I is a multi-dimensional index of matrix elements. In case of + multi-channel matrices, each channel is processed independently. +Output matrix must be of the same size and depth as src1. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.max" +@param src1 first input matrix. +@param src2 second input matrix of the same size and depth as src1. +@sa min, compare, cmpEQ, cmpGT, cmpGE +*/ +GAPI_EXPORTS_W GMat max(const GMat& src1, const GMat& src2); + +/** @brief Calculates the per-element absolute difference between two matrices. + +The function absDiff calculates absolute difference between two matrices of the same size and depth: + \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{src2}(I)|)\f] + where I is a multi-dimensional index of matrix elements. In case of + multi-channel matrices, each channel is processed independently. +Output matrix must have the same size and depth as input matrices. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.absdiff" +@param src1 first input matrix. +@param src2 second input matrix. +@sa abs +*/ +GAPI_EXPORTS_W GMat absDiff(const GMat& src1, const GMat& src2); + +/** @brief Calculates absolute value of matrix elements. + +The function abs calculates absolute difference between matrix elements and given scalar value: + \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{matC}(I)|)\f] + where matC is constructed from given scalar c and has the same sizes and depth as input matrix src. + +Output matrix must be of the same size and depth as src. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.absdiffC" +@param src input matrix. +@param c scalar to be subtracted. +@sa min, max +*/ +GAPI_EXPORTS_W GMat absDiffC(const GMat& src, const GScalar& c); + +/** @brief Calculates sum of all matrix elements. + +The function sum calculates sum of all matrix elements, independently for each channel. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.sum" +@param src input matrix. +@sa countNonZero, mean, min, max +*/ +GAPI_EXPORTS_W GScalar sum(const GMat& src); + +/** @brief Counts non-zero array elements. + +The function returns the number of non-zero elements in src : +\f[\sum _{I: \; \texttt{src} (I) \ne0 } 1\f] + +Supported matrix data types are @ref CV_8UC1, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.countNonZero" +@param src input single-channel matrix. +@sa mean, min, max +*/ +GAPI_EXPORTS_W GOpaque countNonZero(const GMat& src); + +/** @brief Calculates the weighted sum of two matrices. + +The function addWeighted calculates the weighted sum of two matrices as follows: +\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I)* \texttt{alpha} + \texttt{src2} (I)* \texttt{beta} + \texttt{gamma} )\f] +where I is a multi-dimensional index of array elements. In case of multi-channel matrices, each +channel is processed independently. + +The function can be replaced with a matrix expression: + \f[\texttt{dst}(I) = \texttt{alpha} * \texttt{src1}(I) - \texttt{beta} * \texttt{src2}(I) + \texttt{gamma} \f] + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.addweighted" +@param src1 first input matrix. +@param alpha weight of the first matrix elements. +@param src2 second input matrix of the same size and channel number as src1. +@param beta weight of the second matrix elements. +@param gamma scalar added to each sum. +@param ddepth optional depth of the output matrix. +@sa add, sub +*/ +GAPI_EXPORTS_W GMat addWeighted(const GMat& src1, double alpha, const GMat& src2, double beta, double gamma, int ddepth = -1); + +/** @brief Calculates the absolute L1 norm of a matrix. + +This version of normL1 calculates the absolute L1 norm of src. + +As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$. +The \f$ L_{1} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$ +is calculated as follows +\f{align*} + \| r(-1) \|_{L_1} &= |-1| + |2| = 3 \\ +\f} +and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is +\f{align*} + \| r(0.5) \|_{L_1} &= |0.5| + |0.5| = 1 \\ +\f} + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.norml1" +@param src input matrix. +@sa normL2, normInf +*/ +GAPI_EXPORTS_W GScalar normL1(const GMat& src); + +/** @brief Calculates the absolute L2 norm of a matrix. + +This version of normL2 calculates the absolute L2 norm of src. + +As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$. +The \f$ L_{2} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$ +is calculated as follows +\f{align*} + \| r(-1) \|_{L_2} &= \sqrt{(-1)^{2} + (2)^{2}} = \sqrt{5} \\ +\f} +and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is +\f{align*} + \| r(0.5) \|_{L_2} &= \sqrt{(0.5)^{2} + (0.5)^{2}} = \sqrt{0.5} \\ +\f} + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +@note Function textual ID is "org.opencv.core.matrixop.norml2" +@param src input matrix. +@sa normL1, normInf +*/ +GAPI_EXPORTS_W GScalar normL2(const GMat& src); + +/** @brief Calculates the absolute infinite norm of a matrix. + +This version of normInf calculates the absolute infinite norm of src. + +As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$. +The \f$ L_{\infty} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$ +is calculated as follows +\f{align*} + \| r(-1) \|_{L_\infty} &= \max(|-1|,|2|) = 2 +\f} +and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is +\f{align*} + \| r(0.5) \|_{L_\infty} &= \max(|0.5|,|0.5|) = 0.5. +\f} + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.core.matrixop.norminf" +@param src input matrix. +@sa normL1, normL2 +*/ +GAPI_EXPORTS_W GScalar normInf(const GMat& src); + +/** @brief Calculates the integral of an image. + +The function calculates one or more integral images for the source image as follows: + +\f[\texttt{sum} (X,Y) = \sum _{x integral(const GMat& src, int sdepth = -1, int sqdepth = -1); + +/** @brief Applies a fixed-level threshold to each matrix element. + +The function applies fixed-level thresholding to a single- or multiple-channel matrix. +The function is typically used to get a bi-level (binary) image out of a grayscale image ( cmp functions could be also used for +this purpose) or for removing a noise, that is, filtering out pixels with too small or too large +values. There are several types of thresholding supported by the function. They are determined by +type parameter. + +Also, the special values cv::THRESH_OTSU or cv::THRESH_TRIANGLE may be combined with one of the +above values. In these cases, the function determines the optimal threshold value using the Otsu's +or Triangle algorithm and uses it instead of the specified thresh . The function returns the +computed threshold value in addititon to thresholded matrix. +The Otsu's and Triangle methods are implemented only for 8-bit matrices. + +Input image should be single channel only in case of cv::THRESH_OTSU or cv::THRESH_TRIANGLE flags. +Output matrix must be of the same size and depth as src. + +@note Function textual ID is "org.opencv.core.matrixop.threshold" + +@param src input matrix (@ref CV_8UC1, @ref CV_8UC3, or @ref CV_32FC1). +@param thresh threshold value. +@param maxval maximum value to use with the cv::THRESH_BINARY and cv::THRESH_BINARY_INV thresholding +types. +@param type thresholding type (see the cv::ThresholdTypes). + +@sa min, max, cmpGT, cmpLE, cmpGE, cmpLT + */ +GAPI_EXPORTS_W GMat threshold(const GMat& src, const GScalar& thresh, const GScalar& maxval, int type); +/** @overload +This function applicable for all threshold types except cv::THRESH_OTSU and cv::THRESH_TRIANGLE +@note Function textual ID is "org.opencv.core.matrixop.thresholdOT" +*/ +GAPI_EXPORTS_W std::tuple threshold(const GMat& src, const GScalar& maxval, int type); + +/** @brief Applies a range-level threshold to each matrix element. + +The function applies range-level thresholding to a single- or multiple-channel matrix. +It sets output pixel value to OxFF if the corresponding pixel value of input matrix is in specified range,or 0 otherwise. + +Input and output matrices must be CV_8UC1. + +@note Function textual ID is "org.opencv.core.matrixop.inRange" + +@param src input matrix (CV_8UC1). +@param threshLow lower boundary value. +@param threshUp upper boundary value. + +@sa threshold + */ +GAPI_EXPORTS_W GMat inRange(const GMat& src, const GScalar& threshLow, const GScalar& threshUp); + +//! @} gapi_matrixop + +//! @addtogroup gapi_transform +//! @{ +/** @brief Creates one 4-channel matrix out of 4 single-channel ones. + +The function merges several matrices to make a single multi-channel matrix. That is, each +element of the output matrix will be a concatenation of the elements of the input matrices, where +elements of i-th input matrix are treated as mv[i].channels()-element vectors. +Output matrix must be of @ref CV_8UC4 type. + +The function split4 does the reverse operation. + +@note + - Function textual ID is "org.opencv.core.transform.merge4" + +@param src1 first input @ref CV_8UC1 matrix to be merged. +@param src2 second input @ref CV_8UC1 matrix to be merged. +@param src3 third input @ref CV_8UC1 matrix to be merged. +@param src4 fourth input @ref CV_8UC1 matrix to be merged. +@sa merge3, split4, split3 +*/ +GAPI_EXPORTS_W GMat merge4(const GMat& src1, const GMat& src2, const GMat& src3, const GMat& src4); + +/** @brief Creates one 3-channel matrix out of 3 single-channel ones. + +The function merges several matrices to make a single multi-channel matrix. That is, each +element of the output matrix will be a concatenation of the elements of the input matrices, where +elements of i-th input matrix are treated as mv[i].channels()-element vectors. +Output matrix must be of @ref CV_8UC3 type. + +The function split3 does the reverse operation. + +@note + - Function textual ID is "org.opencv.core.transform.merge3" + +@param src1 first input @ref CV_8UC1 matrix to be merged. +@param src2 second input @ref CV_8UC1 matrix to be merged. +@param src3 third input @ref CV_8UC1 matrix to be merged. +@sa merge4, split4, split3 +*/ +GAPI_EXPORTS_W GMat merge3(const GMat& src1, const GMat& src2, const GMat& src3); + +/** @brief Divides a 4-channel matrix into 4 single-channel matrices. + +The function splits a 4-channel matrix into 4 single-channel matrices: +\f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f] + +All output matrices must be of @ref CV_8UC1 type. + +The function merge4 does the reverse operation. + +@note + - Function textual ID is "org.opencv.core.transform.split4" + +@param src input @ref CV_8UC4 matrix. +@sa split3, merge3, merge4 +*/ +GAPI_EXPORTS_W std::tuple split4(const GMat& src); + +/** @brief Divides a 3-channel matrix into 3 single-channel matrices. + +The function splits a 3-channel matrix into 3 single-channel matrices: +\f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f] + +All output matrices must be of @ref CV_8UC1 type. + +The function merge3 does the reverse operation. + +@note + - Function textual ID is "org.opencv.core.transform.split3" + +@param src input @ref CV_8UC3 matrix. +@sa split4, merge3, merge4 +*/ +GAPI_EXPORTS_W std::tuple split3(const GMat& src); + +/** @brief Applies a generic geometrical transformation to an image. + +The function remap transforms the source image using the specified map: + +\f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f] + +where values of pixels with non-integer coordinates are computed using one of available +interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps +in \f$map_1\f$ and \f$map_2\f$ respectively, or interleaved floating-point maps of \f$(x,y)\f$ in +\f$map_1\f$, or fixed-point maps created by using convertMaps. The reason you might want to +convert from floating to fixed-point representations of a map is that they can yield much faster +(\~2x) remapping operations. In the converted case, \f$map_1\f$ contains pairs (cvFloor(x), +cvFloor(y)) and \f$map_2\f$ contains indices in a table of interpolation coefficients. +Output image must be of the same size and depth as input one. + +@note + - Function textual ID is "org.opencv.core.transform.remap" + - Due to current implementation limitations the size of an input and output images should be less than 32767x32767. + +@param src Source image. +@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2, +CV_32FC1, or CV_32FC2. +@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map +if map1 is (x,y) points), respectively. +@param interpolation Interpolation method (see cv::InterpolationFlags). The methods #INTER_AREA +and #INTER_LINEAR_EXACT are not supported by this function. +@param borderMode Pixel extrapolation method (see cv::BorderTypes). When +borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image that +corresponds to the "outliers" in the source image are not modified by the function. +@param borderValue Value used in case of a constant border. By default, it is 0. + */ +GAPI_EXPORTS_W GMat remap(const GMat& src, const Mat& map1, const Mat& map2, + int interpolation, int borderMode = BORDER_CONSTANT, + const Scalar& borderValue = Scalar()); + +/** @brief Flips a 2D matrix around vertical, horizontal, or both axes. + +The function flips the matrix in one of three different ways (row +and column indices are 0-based): +\f[\texttt{dst} _{ij} = +\left\{ +\begin{array}{l l} +\texttt{src} _{\texttt{src.rows}-i-1,j} & if\; \texttt{flipCode} = 0 \\ +\texttt{src} _{i, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} > 0 \\ +\texttt{src} _{ \texttt{src.rows} -i-1, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} < 0 \\ +\end{array} +\right.\f] +The example scenarios of using the function are the following: +* Vertical flipping of the image (flipCode == 0) to switch between + top-left and bottom-left image origin. This is a typical operation + in video processing on Microsoft Windows\* OS. +* Horizontal flipping of the image with the subsequent horizontal + shift and absolute difference calculation to check for a + vertical-axis symmetry (flipCode \> 0). +* Simultaneous horizontal and vertical flipping of the image with + the subsequent shift and absolute difference calculation to check + for a central symmetry (flipCode \< 0). +* Reversing the order of point arrays (flipCode \> 0 or + flipCode == 0). +Output image must be of the same depth as input one, size should be correct for given flipCode. + +@note Function textual ID is "org.opencv.core.transform.flip" + +@param src input matrix. +@param flipCode a flag to specify how to flip the array; 0 means +flipping around the x-axis and positive value (for example, 1) means +flipping around y-axis. Negative value (for example, -1) means flipping +around both axes. +@sa remap +*/ +GAPI_EXPORTS_W GMat flip(const GMat& src, int flipCode); + +/** @brief Crops a 2D matrix. + +The function crops the matrix by given cv::Rect. + +Output matrix must be of the same depth as input one, size is specified by given rect size. + +@note Function textual ID is "org.opencv.core.transform.crop" + +@param src input matrix. +@param rect a rect to crop a matrix to +@sa resize +*/ +GAPI_EXPORTS_W GMat crop(const GMat& src, const Rect& rect); + +/** @brief Applies horizontal concatenation to given matrices. + +The function horizontally concatenates two GMat matrices (with the same number of rows). +@code{.cpp} + GMat A = { 1, 4, + 2, 5, + 3, 6 }; + GMat B = { 7, 10, + 8, 11, + 9, 12 }; + + GMat C = gapi::concatHor(A, B); + //C: + //[1, 4, 7, 10; + // 2, 5, 8, 11; + // 3, 6, 9, 12] +@endcode +Output matrix must the same number of rows and depth as the src1 and src2, and the sum of cols of the src1 and src2. +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.imgproc.transform.concatHor" + +@param src1 first input matrix to be considered for horizontal concatenation. +@param src2 second input matrix to be considered for horizontal concatenation. +@sa concatVert +*/ +GAPI_EXPORTS_W GMat concatHor(const GMat& src1, const GMat& src2); + +/** @overload +The function horizontally concatenates given number of GMat matrices (with the same number of columns). +Output matrix must the same number of columns and depth as the input matrices, and the sum of rows of input matrices. + +@param v vector of input matrices to be concatenated horizontally. +*/ +GAPI_EXPORTS_W GMat concatHor(const std::vector &v); + +/** @brief Applies vertical concatenation to given matrices. + +The function vertically concatenates two GMat matrices (with the same number of cols). + @code{.cpp} + GMat A = { 1, 7, + 2, 8, + 3, 9 }; + GMat B = { 4, 10, + 5, 11, + 6, 12 }; + + GMat C = gapi::concatVert(A, B); + //C: + //[1, 7; + // 2, 8; + // 3, 9; + // 4, 10; + // 5, 11; + // 6, 12] + @endcode + +Output matrix must the same number of cols and depth as the src1 and src2, and the sum of rows of the src1 and src2. +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. + +@note Function textual ID is "org.opencv.imgproc.transform.concatVert" + +@param src1 first input matrix to be considered for vertical concatenation. +@param src2 second input matrix to be considered for vertical concatenation. +@sa concatHor +*/ +GAPI_EXPORTS_W GMat concatVert(const GMat& src1, const GMat& src2); + +/** @overload +The function vertically concatenates given number of GMat matrices (with the same number of columns). +Output matrix must the same number of columns and depth as the input matrices, and the sum of rows of input matrices. + +@param v vector of input matrices to be concatenated vertically. +*/ +GAPI_EXPORTS_W GMat concatVert(const std::vector &v); + + +/** @brief Performs a look-up table transform of a matrix. + +The function LUT fills the output matrix with values from the look-up table. Indices of the entries +are taken from the input matrix. That is, the function processes each element of src as follows: +\f[\texttt{dst} (I) \leftarrow \texttt{lut(src(I))}\f] + +Supported matrix data types are @ref CV_8UC1. +Output is a matrix of the same size and number of channels as src, and the same depth as lut. + +@note Function textual ID is "org.opencv.core.transform.LUT" + +@param src input matrix of 8-bit elements. +@param lut look-up table of 256 elements; in case of multi-channel input array, the table should +either have a single channel (in this case the same table is used for all channels) or the same +number of channels as in the input matrix. +*/ +GAPI_EXPORTS_W GMat LUT(const GMat& src, const Mat& lut); + +/** @brief Converts a matrix to another data depth with optional scaling. + +The method converts source pixel values to the target data depth. saturate_cast\<\> is applied at +the end to avoid possible overflows: + +\f[m(x,y) = saturate \_ cast( \alpha (*this)(x,y) + \beta )\f] +Output matrix must be of the same size as input one. + +@note Function textual ID is "org.opencv.core.transform.convertTo" +@param src input matrix to be converted from. +@param rdepth desired output matrix depth or, rather, the depth since the number of channels are the +same as the input has; if rdepth is negative, the output matrix will have the same depth as the input. +@param alpha optional scale factor. +@param beta optional delta added to the scaled values. + */ +GAPI_EXPORTS_W GMat convertTo(const GMat& src, int rdepth, double alpha=1, double beta=0); + +/** @brief Normalizes the norm or value range of an array. + +The function normalizes scale and shift the input array elements so that +\f[\| \texttt{dst} \| _{L_p}= \texttt{alpha}\f] +(where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that +\f[\min _I \texttt{dst} (I)= \texttt{alpha} , \, \, \max _I \texttt{dst} (I)= \texttt{beta}\f] +when normType=NORM_MINMAX (for dense arrays only). + +@note Function textual ID is "org.opencv.core.normalize" + +@param src input array. +@param alpha norm value to normalize to or the lower range boundary in case of the range +normalization. +@param beta upper range boundary in case of the range normalization; it is not used for the norm +normalization. +@param norm_type normalization type (see cv::NormTypes). +@param ddepth when negative, the output array has the same type as src; otherwise, it has the same +number of channels as src and the depth =ddepth. +@sa norm, Mat::convertTo +*/ +GAPI_EXPORTS_W GMat normalize(const GMat& src, double alpha, double beta, + int norm_type, int ddepth = -1); + +/** @brief Applies a perspective transformation to an image. + +The function warpPerspective transforms the source image using the specified matrix: + +\f[\texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} , + \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )\f] + +when the flag #WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invert +and then put in the formula above instead of M. The function cannot operate in-place. + +@param src input image. +@param M \f$3\times 3\f$ transformation matrix. +@param dsize size of the output image. +@param flags combination of interpolation methods (#INTER_LINEAR or #INTER_NEAREST) and the +optional flag #WARP_INVERSE_MAP, that sets M as the inverse transformation ( +\f$\texttt{dst}\rightarrow\texttt{src}\f$ ). +@param borderMode pixel extrapolation method (#BORDER_CONSTANT or #BORDER_REPLICATE). +@param borderValue value used in case of a constant border; by default, it equals 0. + +@sa warpAffine, resize, remap, getRectSubPix, perspectiveTransform + */ +GAPI_EXPORTS_W GMat warpPerspective(const GMat& src, const Mat& M, const Size& dsize, int flags = cv::INTER_LINEAR, + int borderMode = cv::BORDER_CONSTANT, const Scalar& borderValue = Scalar()); + +/** @brief Applies an affine transformation to an image. + +The function warpAffine transforms the source image using the specified matrix: + +\f[\texttt{dst} (x,y) = \texttt{src} ( \texttt{M} _{11} x + \texttt{M} _{12} y + \texttt{M} _{13}, \texttt{M} _{21} x + \texttt{M} _{22} y + \texttt{M} _{23})\f] + +when the flag #WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted +with #invertAffineTransform and then put in the formula above instead of M. The function cannot +operate in-place. + +@param src input image. +@param M \f$2\times 3\f$ transformation matrix. +@param dsize size of the output image. +@param flags combination of interpolation methods (see #InterpolationFlags) and the optional +flag #WARP_INVERSE_MAP that means that M is the inverse transformation ( +\f$\texttt{dst}\rightarrow\texttt{src}\f$ ). +@param borderMode pixel extrapolation method (see #BorderTypes); +borderMode=#BORDER_TRANSPARENT isn't supported +@param borderValue value used in case of a constant border; by default, it is 0. + +@sa warpPerspective, resize, remap, getRectSubPix, transform + */ +GAPI_EXPORTS_W GMat warpAffine(const GMat& src, const Mat& M, const Size& dsize, int flags = cv::INTER_LINEAR, + int borderMode = cv::BORDER_CONSTANT, const Scalar& borderValue = Scalar()); +//! @} gapi_transform + +/** @brief Finds centers of clusters and groups input samples around the clusters. + +The function kmeans implements a k-means algorithm that finds the centers of K clusters +and groups the input samples around the clusters. As an output, \f$\texttt{bestLabels}_i\f$ +contains a 0-based cluster index for the \f$i^{th}\f$ sample. + +@note + - Function textual ID is "org.opencv.core.kmeansND" + - In case of an N-dimentional points' set given, input GMat can have the following traits: +2 dimensions, a single row or column if there are N channels, +or N columns if there is a single channel. Mat should have @ref CV_32F depth. + - Although, if GMat with height != 1, width != 1, channels != 1 given as data, n-dimensional +samples are considered given in amount of A, where A = height, n = width * channels. + - In case of GMat given as data: + - the output labels are returned as 1-channel GMat with sizes +width = 1, height = A, where A is samples amount, or width = bestLabels.width, +height = bestLabels.height if bestLabels given; + - the cluster centers are returned as 1-channel GMat with sizes +width = n, height = K, where n is samples' dimentionality and K is clusters' amount. + - As one of possible usages, if you want to control the initial labels for each attempt +by yourself, you can utilize just the core of the function. To do that, set the number +of attempts to 1, initialize labels each time using a custom algorithm, pass them with the +( flags = #KMEANS_USE_INITIAL_LABELS ) flag, and then choose the best (most-compact) clustering. + +@param data Data for clustering. An array of N-Dimensional points with float coordinates is needed. +Function can take GArray, GArray for 2D and 3D cases or GMat for any +dimentionality and channels. +@param K Number of clusters to split the set by. +@param bestLabels Optional input integer array that can store the supposed initial cluster indices +for every sample. Used when ( flags = #KMEANS_USE_INITIAL_LABELS ) flag is set. +@param criteria The algorithm termination criteria, that is, the maximum number of iterations +and/or the desired accuracy. The accuracy is specified as criteria.epsilon. As soon as each of +the cluster centers moves by less than criteria.epsilon on some iteration, the algorithm stops. +@param attempts Flag to specify the number of times the algorithm is executed using different +initial labellings. The algorithm returns the labels that yield the best compactness (see the first +function return value). +@param flags Flag that can take values of cv::KmeansFlags . + +@return + - Compactness measure that is computed as +\f[\sum _i \| \texttt{samples} _i - \texttt{centers} _{ \texttt{labels} _i} \| ^2\f] +after every attempt. The best (minimum) value is chosen and the corresponding labels and the +compactness value are returned by the function. + - Integer array that stores the cluster indices for every sample. + - Array of the cluster centers. +*/ +GAPI_EXPORTS_W std::tuple,GMat,GMat> +kmeans(const GMat& data, const int K, const GMat& bestLabels, + const TermCriteria& criteria, const int attempts, const KmeansFlags flags); + +/** @overload +@note + - Function textual ID is "org.opencv.core.kmeansNDNoInit" + - #KMEANS_USE_INITIAL_LABELS flag must not be set while using this overload. + */ +GAPI_EXPORTS_W std::tuple,GMat,GMat> +kmeans(const GMat& data, const int K, const TermCriteria& criteria, const int attempts, + const KmeansFlags flags); + +/** @overload +@note Function textual ID is "org.opencv.core.kmeans2D" + */ +GAPI_EXPORTS_W std::tuple,GArray,GArray> +kmeans(const GArray& data, const int K, const GArray& bestLabels, + const TermCriteria& criteria, const int attempts, const KmeansFlags flags); + +/** @overload +@note Function textual ID is "org.opencv.core.kmeans3D" + */ +GAPI_EXPORTS_W std::tuple,GArray,GArray> +kmeans(const GArray& data, const int K, const GArray& bestLabels, + const TermCriteria& criteria, const int attempts, const KmeansFlags flags); + + +/** @brief Transposes a matrix. + +The function transposes the matrix: +\f[\texttt{dst} (i,j) = \texttt{src} (j,i)\f] + +@note + - Function textual ID is "org.opencv.core.transpose" + - No complex conjugation is done in case of a complex matrix. It should be done separately if needed. + +@param src input array. +*/ +GAPI_EXPORTS_W GMat transpose(const GMat& src); + + +namespace streaming { +/** @brief Gets dimensions from Mat. + +@note Function textual ID is "org.opencv.streaming.size" + +@param src Input tensor +@return Size (tensor dimensions). +*/ +GAPI_EXPORTS_W GOpaque size(const GMat& src); + +/** @overload +Gets dimensions from rectangle. + +@note Function textual ID is "org.opencv.streaming.sizeR" + +@param r Input rectangle. +@return Size (rectangle dimensions). +*/ +GAPI_EXPORTS_W GOpaque size(const GOpaque& r); + +/** @brief Gets dimensions from MediaFrame. + +@note Function textual ID is "org.opencv.streaming.sizeMF" + +@param src Input frame +@return Size (frame dimensions). +*/ +GAPI_EXPORTS_W GOpaque size(const GFrame& src); +} //namespace streaming +} //namespace gapi +} //namespace cv + +#endif //OPENCV_GAPI_CORE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ee86fb72c234f9dc373e9703064249b420671b8e --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/core.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_CPU_CORE_API_HPP +#define OPENCV_GAPI_CPU_CORE_API_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { +namespace gapi { +namespace core { +namespace cpu { + +GAPI_EXPORTS_W cv::GKernelPackage kernels(); + +} // namespace cpu +} // namespace core +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_CORE_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eb5f7847478c658fe50c202296d161ec2ec5f380 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp @@ -0,0 +1,542 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2022 Intel Corporation + + +#ifndef OPENCV_GAPI_GCPUKERNEL_HPP +#define OPENCV_GAPI_GCPUKERNEL_HPP + +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // "Unreachable code" on postprocess(...) call inside OCVCallHelper +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include //suppress_unused_warning +#include + +// FIXME: namespace scheme for backends? +namespace cv { + +namespace gimpl +{ + // Forward-declare an internal class + class GCPUExecutable; +} // namespace gimpl + +namespace gapi +{ +/** + * @brief This namespace contains G-API CPU backend functions, + * structures, and symbols. + */ +namespace cpu +{ + /** + * \addtogroup gapi_std_backends + * @{ + * + * @brief G-API backends available in this OpenCV version + * + * G-API backends play a corner stone role in G-API execution + * stack. Every backend is hardware-oriented and thus can run its + * kernels efficiently on the target platform. + * + * Backends are usually "black boxes" for G-API users -- on the API + * side, all backends are represented as different objects of the + * same class cv::gapi::GBackend. + * User can manipulate with backends by specifying which kernels to use. + * + * @sa @ref gapi_hld + */ + + /** + * @brief Get a reference to CPU (OpenCV) backend. + * + * This is the default backend in G-API at the moment, providing + * broader functional coverage but losing some graph model + * advantages. Provided mostly for reference and prototyping + * purposes. + * + * @sa gapi_std_backends + */ + GAPI_EXPORTS cv::gapi::GBackend backend(); + /** @} */ + + class GOCVFunctor; + + //! @cond IGNORED + template + GOCVFunctor ocv_kernel(const Callable& c); + + template + GOCVFunctor ocv_kernel(Callable& c); + //! @endcond + +} // namespace cpu +} // namespace gapi + +// Represents arguments which are passed to a wrapped CPU function +// FIXME: put into detail? +class GAPI_EXPORTS GCPUContext +{ +public: + // Generic accessor API + template + const T& inArg(int input) { return m_args.at(input).get(); } + + // Syntax sugar + const cv::Mat& inMat(int input); + cv::Mat& outMatR(int output); // FIXME: Avoid cv::Mat m = ctx.outMatR() + + const cv::Scalar& inVal(int input); + cv::Scalar& outValR(int output); // FIXME: Avoid cv::Scalar s = ctx.outValR() + cv::MediaFrame& outFrame(int output); + template std::vector& outVecR(int output) // FIXME: the same issue + { + return outVecRef(output).wref(); + } + template T& outOpaqueR(int output) // FIXME: the same issue + { + return outOpaqueRef(output).wref(); + } + + GArg state() + { + return m_state; + } + +protected: + detail::VectorRef& outVecRef(int output); + detail::OpaqueRef& outOpaqueRef(int output); + + std::vector m_args; + GArg m_state; + + //FIXME: avoid conversion of arguments from internal representation to OpenCV one on each call + //to OCV kernel. (This can be achieved by a two single time conversions in GCPUExecutable::run, + //once on enter for input and output arguments, and once before return for output arguments only + std::unordered_map m_results; + + friend class gimpl::GCPUExecutable; +}; + +class GAPI_EXPORTS GCPUKernel +{ +public: + // This function is a kernel's execution entry point (does the processing work) + using RunF = std::function; + // This function is a stateful kernel's setup routine (configures state) + using SetupF = std::function; + + GCPUKernel(); + GCPUKernel(const RunF& runF, const SetupF& setupF = nullptr); + + RunF m_runF = nullptr; + SetupF m_setupF = nullptr; + + bool m_isStateful = false; +}; + +// FIXME: This is an ugly ad-hoc implementation. TODO: refactor + +namespace detail +{ +template struct get_in; +template<> struct get_in +{ + static cv::Mat get(GCPUContext &ctx, int idx) { return ctx.inMat(idx); } +}; +template<> struct get_in +{ + static cv::Mat get(GCPUContext &ctx, int idx) { return get_in::get(ctx, idx); } +}; +template<> struct get_in +{ + static cv::MediaFrame get(GCPUContext &ctx, int idx) { return ctx.inArg(idx); } +}; +template<> struct get_in +{ + static cv::Scalar get(GCPUContext &ctx, int idx) { return ctx.inVal(idx); } +}; +template struct get_in > +{ + static const std::vector& get(GCPUContext &ctx, int idx) { return ctx.inArg(idx).rref(); } +}; +template struct get_in > +{ + static const U& get(GCPUContext &ctx, int idx) { return ctx.inArg(idx).rref(); } +}; + +//FIXME(dm): GArray/GArray conversion should be done more gracefully in the system +template<> struct get_in >: public get_in > +{ +}; + +//FIXME(dm): GArray/GArray conversion should be done more gracefully in the system +template<> struct get_in >: public get_in > +{ +}; + +// FIXME(dm): GArray>/GArray> conversion should be done more gracefully in the system +template struct get_in> >: public get_in> > +{ +}; + +//FIXME(dm): GOpaque/GOpaque conversion should be done more gracefully in the system +template<> struct get_in >: public get_in > +{ +}; + +//FIXME(dm): GOpaque/GOpaque conversion should be done more gracefully in the system +template<> struct get_in >: public get_in > +{ +}; + +template struct get_in +{ + static T get(GCPUContext &ctx, int idx) { return ctx.inArg(idx); } +}; + +struct tracked_cv_mat{ + tracked_cv_mat(cv::Mat& m) : r{m}, original_data{m.data} {} + cv::Mat r; + uchar* original_data; + + operator cv::Mat& (){ return r;} + void validate() const{ + if (r.data != original_data) + { + util::throw_error + (std::logic_error + ("OpenCV kernel output parameter was reallocated. \n" + "Incorrect meta data was provided ?")); + } + } +}; + +template +void postprocess(Outputs&... outs) +{ + struct + { + void operator()(tracked_cv_mat* bm) { bm->validate(); } + void operator()(...) { } + + } validate; + //dummy array to unfold parameter pack + int dummy[] = { 0, (validate(&outs), 0)... }; + cv::util::suppress_unused_warning(dummy); +} + +template struct get_out; +template<> struct get_out +{ + static tracked_cv_mat get(GCPUContext &ctx, int idx) + { + auto& r = ctx.outMatR(idx); + return {r}; + } +}; +template<> struct get_out +{ + static tracked_cv_mat get(GCPUContext &ctx, int idx) + { + return get_out::get(ctx, idx); + } +}; +template<> struct get_out +{ + static cv::Scalar& get(GCPUContext &ctx, int idx) + { + return ctx.outValR(idx); + } +}; +template<> struct get_out +{ + static cv::MediaFrame& get(GCPUContext &ctx, int idx) + { + return ctx.outFrame(idx); + } +}; +template struct get_out> +{ + static std::vector& get(GCPUContext &ctx, int idx) + { + return ctx.outVecR(idx); + } +}; + +//FIXME(dm): GArray/GArray conversion should be done more gracefully in the system +template<> struct get_out >: public get_out > +{ +}; + +// FIXME(dm): GArray>/GArray> conversion should be done more gracefully in the system +template struct get_out> >: public get_out> > +{ +}; + +template struct get_out> +{ + static U& get(GCPUContext &ctx, int idx) + { + return ctx.outOpaqueR(idx); + } +}; + +template +struct OCVSetupHelper; + +template +struct OCVSetupHelper> +{ + // Using 'auto' return type and 'decltype' specifier in both 'setup_impl' versions + // to check existence of required 'Impl::setup' functions. + // While 'decltype' specifier accepts expression we pass expression with 'comma-operator' + // where first operand of comma-operator is call attempt to desired 'Impl::setup' and + // the second operand is 'void()' expression. + // + // SFINAE for 'Impl::setup' which accepts compile arguments. + template + static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args, + GArg &state, const GCompileArgs &compileArgs, + detail::Seq) -> + decltype(Impl::setup(detail::get_in_meta(metaArgs, args, IIs)..., + std::declval + >::type + >(), + compileArgs) + , void()) + { + // TODO: unique_ptr <-> shared_ptr conversion ? + // To check: Conversion is possible only if the state which should be passed to + // 'setup' user callback isn't required to have previous value + std::shared_ptr stPtr; + Impl::setup(detail::get_in_meta(metaArgs, args, IIs)..., stPtr, compileArgs); + state = GArg(stPtr); + } + + // SFINAE for 'Impl::setup' which doesn't accept compile arguments. + template + static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args, + GArg &state, const GCompileArgs &/* compileArgs */, + detail::Seq) -> + decltype(Impl::setup(detail::get_in_meta(metaArgs, args, IIs)..., + std::declval + >::type + >() + ) + , void()) + { + // The same comment as in 'setup' above. + std::shared_ptr stPtr; + Impl::setup(detail::get_in_meta(metaArgs, args, IIs)..., stPtr); + state = GArg(stPtr); + } + + static void setup(const GMetaArgs &metaArgs, const GArgs &args, + GArg& state, const GCompileArgs &compileArgs) + { + setup_impl(metaArgs, args, state, compileArgs, + typename detail::MkSeq::type()); + } +}; + +// OCVCallHelper is a helper class to call stateless OCV kernels and OCV kernel functors. +template +struct OCVCallHelper; + +// FIXME: probably can be simplified with std::apply or analogue. +template +struct OCVCallHelper, std::tuple> +{ + template + struct call_and_postprocess + { + template + static void call(Inputs&&... ins, Outputs&&... outs) + { + //not using a std::forward on outs is deliberate in order to + //cause compilation error, by trying to bind rvalue references to lvalue references + Impl::run(std::forward(ins)..., outs...); + postprocess(outs...); + } + + template + static void call(Impl& impl, Inputs&&... ins, Outputs&&... outs) + { + impl(std::forward(ins)..., outs...); + } + }; + + template + static void call_impl(GCPUContext &ctx, detail::Seq, detail::Seq) + { + //Make sure that OpenCV kernels do not reallocate memory for output parameters + //by comparing it's state (data ptr) before and after the call. + //This is done by converting each output Mat into tracked_cv_mat object, and binding + //them to parameters of ad-hoc function + call_and_postprocess::get(ctx, IIs))...> + ::call(get_in::get(ctx, IIs)..., get_out::get(ctx, OIs)...); + } + + template + static void call_impl(cv::GCPUContext &ctx, Impl& impl, + detail::Seq, detail::Seq) + { + call_and_postprocess::get(ctx, IIs))...> + ::call(impl, get_in::get(ctx, IIs)..., get_out::get(ctx, OIs)...); + } + + static void call(GCPUContext &ctx) + { + call_impl(ctx, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } + + // NB: Same as call but calling the object + // This necessary for kernel implementations that have a state + // and are represented as an object + static void callFunctor(cv::GCPUContext &ctx, Impl& impl) + { + call_impl(ctx, impl, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } +}; + +// OCVStCallHelper is a helper class to call stateful OCV kernels. +template +struct OCVStCallHelper; + +template +struct OCVStCallHelper, std::tuple> : + OCVCallHelper, std::tuple> +{ + template + struct call_and_postprocess + { + template + static void call(typename Impl::State& st, Inputs&&... ins, Outputs&&... outs) + { + Impl::run(std::forward(ins)..., outs..., st); + postprocess(outs...); + } + }; + + template + static void call_impl(GCPUContext &ctx, detail::Seq, detail::Seq) + { + auto& st = *ctx.state().get>(); + call_and_postprocess::get(ctx, IIs))...> + ::call(st, get_in::get(ctx, IIs)..., get_out::get(ctx, OIs)...); + } + + static void call(GCPUContext &ctx) + { + call_impl(ctx, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } +}; + +} // namespace detail + +template +class GCPUKernelImpl: public cv::detail::KernelTag +{ + using CallHelper = cv::detail::OCVCallHelper; + +public: + using API = K; + + static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); } + static cv::GCPUKernel kernel() { return GCPUKernel(&CallHelper::call); } +}; + +template +class GCPUStKernelImpl: public cv::detail::KernelTag +{ + using StSetupHelper = detail::OCVSetupHelper; + using StCallHelper = detail::OCVStCallHelper; + +public: + using API = K; + using State = S; + + static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); } + static cv::GCPUKernel kernel() { return GCPUKernel(&StCallHelper::call, + &StSetupHelper::setup); } +}; + +#define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl + +// TODO: Reuse Anatoliy's logic for support of types with commas in macro. +// Retrieve the common part from Anatoliy's logic to the separate place. +#define GAPI_OCV_KERNEL_ST(Name, API, State) \ + struct Name: public cv::GCPUStKernelImpl \ + +/// @private +class gapi::cpu::GOCVFunctor : public gapi::GFunctor +{ +public: + using Impl = std::function; + using Meta = cv::GKernel::M; + + GOCVFunctor(const char* id, const Meta &meta, const Impl& impl) + : gapi::GFunctor(id), impl_{GCPUKernel(impl), meta} + { + } + + GKernelImpl impl() const override { return impl_; } + gapi::GBackend backend() const override { return gapi::cpu::backend(); } + +private: + GKernelImpl impl_; +}; + +//! @cond IGNORED +template +gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(Callable& c) +{ + using P = cv::detail::OCVCallHelper; + return GOCVFunctor{ K::id() + , &K::getOutMeta + , std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c)) + }; +} + +template +gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(const Callable& c) +{ + using P = cv::detail::OCVCallHelper; + return GOCVFunctor{ K::id() + , &K::getOutMeta + , std::bind(&P::callFunctor, std::placeholders::_1, c) + }; +} +//! @endcond + +} // namespace cv + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // OPENCV_GAPI_GCPUKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/imgproc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0b96db08ae18b308ccef80d785a5e002b099b84f --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/imgproc.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_CPU_IMGPROC_API_HPP +#define OPENCV_GAPI_CPU_IMGPROC_API_HPP + +#include // GAPI_EXPORTS +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace imgproc { +namespace cpu { + +GAPI_EXPORTS GKernelPackage kernels(); + +} // namespace cpu +} // namespace imgproc +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_IMGPROC_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/ot.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/ot.hpp new file mode 100644 index 0000000000000000000000000000000000000000..03dbe904cc9d9393369d528f846533486f6ec0ed --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/ot.hpp @@ -0,0 +1,29 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_CPU_OT_API_HPP +#define OPENCV_GAPI_CPU_OT_API_HPP + +#include // GAPI_EXPORTS +#include // GKernelPackage + +namespace cv { +namespace gapi { +/** + * @brief This namespace contains G-API Operation Types for + * VAS Object Tracking module functionality. + */ +namespace ot { +namespace cpu { +GAPI_EXPORTS_W GKernelPackage kernels(); +} // namespace cpu +} // namespace ot +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_OT_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/stereo.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/stereo.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e2a2242bd0b8abb66a638745b809869c1bf99934 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/stereo.hpp @@ -0,0 +1,48 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_CPU_STEREO_API_HPP +#define OPENCV_GAPI_CPU_STEREO_API_HPP + +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace calib3d { +namespace cpu { + +GAPI_EXPORTS GKernelPackage kernels(); + +/** @brief Structure for the Stereo operation initialization parameters.*/ +struct GAPI_EXPORTS StereoInitParam { + StereoInitParam(int nD, int bS, double bL, double f): + numDisparities(nD), blockSize(bS), baseline(bL), focus(f) {} + + StereoInitParam() = default; + + int numDisparities = 0; + int blockSize = 21; + double baseline = 63.5; + double focus = 3.6; +}; + +} // namespace cpu +} // namespace calib3d +} // namespace gapi + +namespace detail { + + template<> struct CompileArgTag { + static const char* tag() { + return "org.opencv.stereoInit"; + } +}; + +} // namespace detail +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_STEREO_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/video.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/video.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d3c1f2e670454e63dd6bb65efeb4d12620d4f2aa --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/cpu/video.hpp @@ -0,0 +1,25 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_CPU_VIDEO_API_HPP +#define OPENCV_GAPI_CPU_VIDEO_API_HPP + +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace video { +namespace cpu { + +GAPI_EXPORTS GKernelPackage kernels(); + +} // namespace cpu +} // namespace video +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_VIDEO_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a4329d6f50f8433142b2be3f1cfa6304ce8f621d --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/core.hpp @@ -0,0 +1,20 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_FLUID_CORE_HPP +#define OPENCV_GAPI_FLUID_CORE_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { namespace gapi { namespace core { namespace fluid { + +GAPI_EXPORTS_W cv::GKernelPackage kernels(); + +}}}} + +#endif // OPENCV_GAPI_FLUID_CORE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidbuffer.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidbuffer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..551f0a398febeb7637b36f90cf8f141549c387c2 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidbuffer.hpp @@ -0,0 +1,154 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_FLUID_BUFFER_HPP +#define OPENCV_GAPI_FLUID_BUFFER_HPP + +#include +#include // accumulate +#include // ostream +#include // uint8_t + +#include +#include + +#include + +namespace cv { +namespace gapi { +namespace fluid { + +struct Border +{ + // This constructor is required to support existing kernels which are part of G-API + Border(int _type, cv::Scalar _val) : type(_type), value(_val) {} + + int type; + cv::Scalar value; +}; + +using BorderOpt = util::optional; + +bool operator == (const Border& b1, const Border& b2); + +class GAPI_EXPORTS Buffer; + +class GAPI_EXPORTS View +{ +public: + struct Cache + { + std::vector m_linePtrs; + GMatDesc m_desc; + int m_border_size = 0; + + inline const uint8_t* linePtr(int index) const + { + // "out_of_window" check: + // user must not request the lines which are outside of specified kernel window + GAPI_DbgAssert(index >= -m_border_size + && index < -m_border_size + static_cast(m_linePtrs.size())); + return m_linePtrs[index + m_border_size]; + } + }; + + const inline uint8_t* InLineB(int index) const // -(w-1)/2...0...+(w-1)/2 for Filters + { + return m_cache->linePtr(index); + } + + template const inline T* InLine(int i) const + { + const uint8_t* ptr = this->InLineB(i); + return reinterpret_cast(ptr); + } + + inline operator bool() const { return m_priv != nullptr; } + bool ready() const; + inline int length() const { return m_cache->m_desc.size.width; } + int y() const; + + inline const GMatDesc& meta() const { return m_cache->m_desc; } + + class GAPI_EXPORTS Priv; // internal use only + Priv& priv(); // internal use only + const Priv& priv() const; // internal use only + + View(); + View(std::unique_ptr&& p); + View(View&& v); + View& operator=(View&& v); + ~View(); + +private: + std::unique_ptr m_priv; + const Cache* m_cache = nullptr; +}; + +class GAPI_EXPORTS Buffer +{ +public: + struct Cache + { + std::vector m_linePtrs; + GMatDesc m_desc; + }; + + // Default constructor (executable creation stage, + // all following initialization performed in Priv::init()) + Buffer(); + // Scratch constructor (user kernels) + Buffer(const cv::GMatDesc &desc); + + // Constructor for intermediate buffers (for tests) + Buffer(const cv::GMatDesc &desc, + int max_line_consumption, int border_size, + int skew, + int wlpi, + BorderOpt border); + // Constructor for in/out buffers (for tests) + Buffer(const cv::Mat &data, bool is_input); + ~Buffer(); + Buffer& operator=(Buffer&&); + + inline uint8_t* OutLineB(int index = 0) + { + return m_cache->m_linePtrs[index]; + } + + template inline T* OutLine(int index = 0) + { + uint8_t* ptr = this->OutLineB(index); + return reinterpret_cast(ptr); + } + + int y() const; + + int linesReady() const; + void debug(std::ostream &os) const; + inline int length() const { return m_cache->m_desc.size.width; } + int lpi() const; // LPI for WRITER + + inline const GMatDesc& meta() const { return m_cache->m_desc; } + + View mkView(int borderSize, bool ownStorage); + void addView(const View* v); + + class GAPI_EXPORTS Priv; // internal use only + Priv& priv(); // internal use only + const Priv& priv() const; // internal use only + +private: + std::unique_ptr m_priv; + const Cache* m_cache; +}; + +} // namespace cv::gapi::fluid +} // namespace cv::gapi +} // namespace cv + +#endif // OPENCV_GAPI_FLUID_BUFFER_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidkernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidkernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c3ae9dfdd6e02ac8a090f0fff6b918b054f09645 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/gfluidkernel.hpp @@ -0,0 +1,442 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2019 Intel Corporation + + +#ifndef OPENCV_GAPI_FLUID_KERNEL_HPP +#define OPENCV_GAPI_FLUID_KERNEL_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +// FIXME: namespace scheme for backends? +namespace cv { + +namespace gapi +{ +/** + * @brief This namespace contains G-API Fluid backend functions, structures, and symbols. + */ +namespace fluid +{ + /** + * \addtogroup gapi_std_backends G-API Standard Backends + * @{ + */ + /** + * @brief Get a reference to Fluid backend. + * + * @sa gapi_std_backends + */ + GAPI_EXPORTS cv::gapi::GBackend backend(); + /** @} */ +} // namespace fluid +} // namespace gapi + + +class GAPI_EXPORTS GFluidKernel +{ +public: + enum class Kind + { + Filter, + Resize, + YUV420toRGB //Color conversion of 4:2:0 chroma sub-sampling formats (NV12, I420 ..etc) to RGB + }; + + // This function is a generic "doWork" callback + using F = std::function &)>; + + // This function is a generic "initScratch" callback + using IS = std::function; + + // This function is a generic "resetScratch" callback + using RS = std::function; + + // This function describes kernel metadata inference rule. + using M = std::function; + + // This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters) + using B = std::function; + + // This function is a generic "getWindow" callback (extracts window-related data from kernel's input parameters) + using GW = std::function; + + // FIXME: move implementations out of header file + GFluidKernel() {} + GFluidKernel(Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b, const GW& win) + : m_kind(k) + , m_lpi(l) + , m_scratch(scratch) + , m_f(f) + , m_is(is) + , m_rs(rs) + , m_b(b) + , m_gw(win) {} + + Kind m_kind; + const int m_lpi = -1; + const bool m_scratch = false; + + const F m_f; + const IS m_is; + const RS m_rs; + const B m_b; + const GW m_gw; +}; + +// FIXME!!! +// This is the temporary and experimental API +// which should be replaced by runtime roi-based scheduling +/** \addtogroup gapi_compile_args + * @{ + */ +/** + * @brief This structure allows to control the output image region + * which Fluid backend will produce in the graph. + * + * This feature is useful for external tiling and parallelism, but + * will be deprecated in the future releases. + */ +struct GFluidOutputRois +{ + std::vector rois; +}; + +/** + * @brief This structure forces Fluid backend to generate multiple + * parallel output regions in the graph. These regions execute in parallel. + * + * This feature may be deprecated in the future releases. + */ +struct GFluidParallelOutputRois +{ + std::vector parallel_rois; +}; + +/** + * @brief This structure allows to customize the way how Fluid executes + * parallel regions. + * + * For example, user can utilize his own threading runtime via this parameter. + * The `parallel_for` member functor is called by the Fluid runtime with the + * following arguments: + * + * @param size Size of the parallel range to process + * @param f A function which should be called for every integer index + * in this range by the specified parallel_for implementation. + * + * This feature may be deprecated in the future releases. + */ +struct GFluidParallelFor +{ + //this function accepts: + // - size of the "parallel" range as the first argument + // - and a function to be called on the range items, designated by item index + std::function)> parallel_for; +}; +/** @} gapi_compile_args */ + +namespace detail +{ +template<> struct CompileArgTag +{ + static const char* tag() { return "gapi.fluid.outputRois"; } +}; + +template<> struct CompileArgTag +{ + static const char* tag() { return "gapi.fluid.parallelFor"; } +}; + +template<> struct CompileArgTag +{ + static const char* tag() { return "gapi.fluid.parallelOutputRois"; } +}; + +} // namespace detail + +namespace detail +{ +template struct fluid_get_in; +template<> struct fluid_get_in +{ + static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx) + { + return *in_args[idx].unsafe_get(); + } +}; + +template<> struct fluid_get_in +{ + // FIXME: change to return by reference when moved to own::Scalar + static cv::Scalar get(const cv::GArgs &in_args, int idx) + { + return in_args[idx].unsafe_get(); + } +}; + +template struct fluid_get_in> +{ + static const std::vector& get(const cv::GArgs &in_args, int idx) + { + return in_args.at(idx).unsafe_get().rref(); + } +}; + +template struct fluid_get_in> +{ + static const U& get(const cv::GArgs &in_args, int idx) + { + return in_args.at(idx).unsafe_get().rref(); + } +}; + +template struct fluid_get_in +{ + static const T& get(const cv::GArgs &in_args, int idx) + { + return in_args[idx].unsafe_get(); + } +}; + +template +struct scratch_helper; + +template +struct scratch_helper +{ + // Init + template + static void help_init_impl(const cv::GMetaArgs &metas, + const cv::GArgs &in_args, + gapi::fluid::Buffer &scratch_buf, + detail::Seq) + { + Impl::initScratch(get_in_meta(metas, in_args, IIs)..., scratch_buf); + } + + static void help_init(const cv::GMetaArgs &metas, + const cv::GArgs &in_args, + gapi::fluid::Buffer &b) + { + help_init_impl(metas, in_args, b, typename detail::MkSeq::type()); + } + + // Reset + static void help_reset(gapi::fluid::Buffer &b) + { + Impl::resetScratch(b); + } +}; + +template +struct scratch_helper +{ + static void help_init(const cv::GMetaArgs &, + const cv::GArgs &, + gapi::fluid::Buffer &) + { + GAPI_Error("InternalError"); + } + static void help_reset(gapi::fluid::Buffer &) + { + GAPI_Error("InternalError"); + } +}; + +template struct is_gmat_type +{ + static const constexpr bool value = std::is_same::value; +}; + +template +struct get_border_helper; + +template +struct get_border_helper +{ + template + static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas, + const cv::GArgs &in_args, + cv::detail::Seq) + { + return util::make_optional(Impl::getBorder(cv::detail::get_in_meta(metas, in_args, IIs)...)); + } + + static gapi::fluid::BorderOpt help(const GMetaArgs &metas, + const cv::GArgs &in_args) + { + return get_border_impl(metas, in_args, typename detail::MkSeq::type()); + } +}; + +template +struct get_border_helper +{ + static gapi::fluid::BorderOpt help(const cv::GMetaArgs &, + const cv::GArgs &) + { + return {}; + } +}; + +template +struct get_window_helper; + +template +struct get_window_helper +{ + template + static int get_window_impl(const GMetaArgs &metas, + const cv::GArgs &in_args, + cv::detail::Seq) + { + return Impl::getWindow(cv::detail::get_in_meta(metas, in_args, IIs)...); + } + + static int help(const GMetaArgs &metas, const cv::GArgs &in_args) + { + return get_window_impl(metas, in_args, typename detail::MkSeq::type()); + } +}; + +template +struct get_window_helper +{ + static int help(const cv::GMetaArgs &, + const cv::GArgs &) + { + return Impl::Window; + } +}; + +template +struct has_Window +{ +private: + template + static constexpr auto Check(U*) -> typename std::is_same::type; + + template + static constexpr std::false_type Check(...); + + typedef decltype(Check(0)) Result; + +public: + static constexpr bool value = Result::value; +}; + +template +struct callCustomGetBorder; + +template +struct callCustomGetBorder +{ + static constexpr bool value = (Impl::Window != 1); +}; + +template +struct callCustomGetBorder +{ + static constexpr bool value = true; +}; + +template +struct FluidCallHelper; + +template +struct FluidCallHelper, std::tuple, UseScratch> +{ + static_assert(all_satisfy::value, "return type must be GMat"); + static_assert(contains::value, "input must contain at least one GMat"); + + // Execution dispatcher //////////////////////////////////////////////////// + template + static void call_impl(const cv::GArgs &in_args, + const std::vector &out_bufs, + detail::Seq, + detail::Seq) + { + Impl::run(fluid_get_in::get(in_args, IIs)..., *out_bufs[OIs]...); + } + + static void call(const cv::GArgs &in_args, + const std::vector &out_bufs) + { + constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0); + call_impl(in_args, out_bufs, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } + + // Scratch buffer initialization dispatcher //////////////////////////////// + static void init_scratch(const GMetaArgs &metas, + const cv::GArgs &in_args, + gapi::fluid::Buffer &b) + { + scratch_helper::help_init(metas, in_args, b); + } + + // Scratch buffer reset dispatcher ///////////////////////////////////////// + static void reset_scratch(gapi::fluid::Buffer &scratch_buf) + { + scratch_helper::help_reset(scratch_buf); + } + + static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args) + { + constexpr bool hasWindow = has_Window::value; + + // User must provide "init" callback if Window != 1 + // TODO: move to constexpr if when we enable C++17 + return get_border_helper::value, Impl, Ins...>::help(metas, in_args); + } + + static int getWindow(const GMetaArgs &metas, const cv::GArgs &in_args) + { + constexpr bool callCustomGetWindow = !(has_Window::value); + return get_window_helper::help(metas, in_args); + } +}; +} // namespace detail + + +template +class GFluidKernelImpl : public cv::detail::KernelTag +{ + static const int LPI = 1; + static const auto Kind = GFluidKernel::Kind::Filter; + using P = detail::FluidCallHelper; + +public: + using API = K; + + static GFluidKernel kernel() + { + // FIXME: call() and getOutMeta() needs to be renamed so it is clear these + // functions are internal wrappers, not user API + return GFluidKernel(Impl::Kind, Impl::LPI, + UseScratch, + &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder, &P::getWindow); + } + + static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); } +}; + +#define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl + +} // namespace cv + +#endif // OPENCV_GAPI_GCPUKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/imgproc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a4e8ac0f9922f303460831426c4b86fc811d778a --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/fluid/imgproc.hpp @@ -0,0 +1,20 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_FLUID_IMGPROC_HPP +#define OPENCV_GAPI_FLUID_IMGPROC_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { namespace gapi { namespace imgproc { namespace fluid { + +GAPI_EXPORTS_W GKernelPackage kernels(); + +}}}} + +#endif // OPENCV_GAPI_FLUID_IMGPROC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garg.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2a8315f9d83ed47590c32edf3e47d889588ff122 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garg.hpp @@ -0,0 +1,311 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_GARG_HPP +#define OPENCV_GAPI_GARG_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cv { + +class GArg; + +namespace detail { + template + using is_garg = std::is_same::type>; +} + +// Parameter holder class for a node +// Depending on platform capabilities, can either support arbitrary types +// (as `boost::any`) or a limited number of types (as `boot::variant`). +// FIXME: put into "details" as a user shouldn't use it in his code +class GAPI_EXPORTS GArg +{ +public: + GArg() {} + + template::value, int>::type = 0> + explicit GArg(const T &t) + : kind(detail::GTypeTraits::kind) + , opaque_kind(detail::GOpaqueTraits::kind) + , value(detail::wrap_gapi_helper::wrap(t)) + { + } + + template::value, int>::type = 0> + explicit GArg(T &&t) + : kind(detail::GTypeTraits::type>::kind) + , opaque_kind(detail::GOpaqueTraits::type>::kind) + , value(detail::wrap_gapi_helper::wrap(t)) + { + } + + template inline T& get() + { + return util::any_cast::type>(value); + } + + template inline const T& get() const + { + return util::any_cast::type>(value); + } + + template inline T& unsafe_get() + { + return util::unsafe_any_cast::type>(value); + } + + template inline const T& unsafe_get() const + { + return util::unsafe_any_cast::type>(value); + } + + detail::ArgKind kind = detail::ArgKind::OPAQUE_VAL; + detail::OpaqueKind opaque_kind = detail::OpaqueKind::CV_UNKNOWN; + +protected: + util::any value; +}; + +using GArgs = std::vector; + +// FIXME: Express as M::type +// FIXME: Move to a separate file! +using GRunArgBase = util::variant< +#if !defined(GAPI_STANDALONE) + cv::UMat, +#endif // !defined(GAPI_STANDALONE) + cv::RMat, + cv::gapi::wip::IStreamSource::Ptr, + cv::Mat, + cv::Scalar, + cv::detail::VectorRef, + cv::detail::OpaqueRef, + cv::MediaFrame + >; + +namespace detail { +template +struct in_variant; + +template +struct in_variant > + : std::integral_constant::value > { +}; +} // namespace detail + +struct GAPI_EXPORTS GRunArg: public GRunArgBase +{ + // Metadata information here + using Meta = std::unordered_map; + Meta meta; + + // Mimic the old GRunArg semantics here, old of the times when + // GRunArg was an alias to variant<> + GRunArg(); + GRunArg(const cv::GRunArg &arg); + GRunArg(cv::GRunArg &&arg); + + GRunArg& operator= (const GRunArg &arg); + GRunArg& operator= (GRunArg &&arg); + + template + GRunArg(const T &t, + const Meta &m = Meta{}, + typename std::enable_if< detail::in_variant::value, int>::type = 0) + : GRunArgBase(t) + , meta(m) + { + } + template + GRunArg(T &&t, + const Meta &m = Meta{}, + typename std::enable_if< detail::in_variant::value, int>::type = 0) + : GRunArgBase(std::move(t)) + , meta(m) + { + } + template auto operator= (const T &t) + -> typename std::enable_if< detail::in_variant::value, cv::GRunArg>::type& + { + GRunArgBase::operator=(t); + return *this; + } + template auto operator= (T&& t) + -> typename std::enable_if< detail::in_variant::value, cv::GRunArg>::type& + { + GRunArgBase::operator=(std::move(t)); + return *this; + } +}; +using GRunArgs = std::vector; + +// TODO: Think about the addition operator +/** + * @brief This operator allows to complement the input vector at runtime. + * + * It's an ordinary overload of addition assignment operator. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GRunArgs usage + * + */ +inline GRunArgs& operator += (GRunArgs &lhs, const GRunArgs &rhs) +{ + lhs.reserve(lhs.size() + rhs.size()); + lhs.insert(lhs.end(), rhs.begin(), rhs.end()); + return lhs; +} + +namespace gapi +{ +namespace wip +{ +/** + * @brief This aggregate type represents all types which G-API can + * handle (via variant). + * + * It only exists to overcome C++ language limitations (where a + * `using`-defined class can't be forward-declared). + */ +struct GAPI_EXPORTS Data: public GRunArg +{ + using GRunArg::GRunArg; + template + Data& operator= (const T& t) { GRunArg::operator=(t); return *this; } + template + Data& operator= (T&& t) { GRunArg::operator=(std::move(t)); return *this; } +}; +} // namespace wip +} // namespace gapi + +using GRunArgP = util::variant< +#if !defined(GAPI_STANDALONE) + cv::UMat*, +#endif // !defined(GAPI_STANDALONE) + cv::Mat*, + cv::RMat*, + cv::Scalar*, + cv::MediaFrame*, + cv::detail::VectorRef, + cv::detail::OpaqueRef + >; +using GRunArgsP = std::vector; + +// TODO: Think about the addition operator +/** + * @brief This operator allows to complement the output vector at runtime. + * + * It's an ordinary overload of addition assignment operator. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GRunArgsP usage + * + */ +inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs) +{ + lhs.reserve(lhs.size() + rhs.size()); + lhs.insert(lhs.end(), rhs.begin(), rhs.end()); + return lhs; +} + +namespace gapi +{ +/** + * \addtogroup gapi_serialization + * @{ + * + * @brief G-API functions and classes for serialization and deserialization. + */ + +/** @brief Wraps deserialized output GRunArgs to GRunArgsP which can be used by GCompiled. + * + * Since it's impossible to get modifiable output arguments from deserialization + * it needs to be wrapped by this function. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp bind after deserialization + * + * @param out_args deserialized GRunArgs. + * @return the same GRunArgs wrapped in GRunArgsP. + * @see deserialize + */ +GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &out_args); + +/** @brief Wraps output GRunArgsP available during graph execution to GRunArgs which can be serialized. + * + * GRunArgsP is pointer-to-value, so to be serialized they need to be binded to real values + * which this function does. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp bind before serialization + * + * @param out output GRunArgsP available during graph execution. + * @return the same GRunArgsP wrapped in serializable GRunArgs. + * @see serialize + */ +GAPI_EXPORTS cv::GRunArg bind(cv::GRunArgP &out); // FIXME: think more about it +/** @} */ +} + +template inline GRunArgs gin(const Ts&... args) +{ + return GRunArgs{ GRunArg(detail::wrap_host_helper::wrap_in(args))... }; +} + +template inline GRunArgsP gout(Ts&... args) +{ + return GRunArgsP{ GRunArgP(detail::wrap_host_helper::wrap_out(args))... }; +} + +struct GTypeInfo; +using GTypesInfo = std::vector; + +// FIXME: Needed for python bridge, must be moved to more appropriate header +namespace detail { +struct ExtractArgsCallback +{ + cv::GRunArgs operator()(const cv::GTypesInfo& info) const { return c(info); } + using CallBackT = std::function; + CallBackT c; +}; + +struct ExtractMetaCallback +{ + cv::GMetaArgs operator()(const cv::GTypesInfo& info) const { return c(info); } + using CallBackT = std::function; + CallBackT c; +}; + +void constructGraphOutputs(const cv::GTypesInfo &out_info, + cv::GRunArgs &args, + cv::GRunArgsP &outs); +} // namespace detail + +} // namespace cv + +#endif // OPENCV_GAPI_GARG_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garray.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garray.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a2951993f2b293d32c99c56a711733ff8a69d59f --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/garray.hpp @@ -0,0 +1,440 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GARRAY_HPP +#define OPENCV_GAPI_GARRAY_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include // flatten_g only! +#include // flatten_g only! + +namespace cv +{ +// Forward declaration; GNode and GOrigin are an internal +// (user-inaccessible) classes. +class GNode; +struct GOrigin; +template class GArray; + +/** + * \addtogroup gapi_meta_args + * @{ + */ +struct GAPI_EXPORTS_W_SIMPLE GArrayDesc +{ + // FIXME: Body + // FIXME: Also implement proper operator== then + bool operator== (const GArrayDesc&) const { return true; } +}; +template GArrayDesc descr_of(const std::vector &) { return {};} +GAPI_EXPORTS_W inline GArrayDesc empty_array_desc() {return {}; } +/** @} */ + +std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc); + +namespace detail +{ + // ConstructVec is a callback which stores information about T and is used by + // G-API runtime to construct arrays in host memory (T remains opaque for G-API). + // ConstructVec is carried into G-API internals by GArrayU. + // Currently it is suitable for Host (CPU) plugins only, real offload may require + // more information for manual memory allocation on-device. + class VectorRef; + using ConstructVec = std::function; + + // This is the base struct for GArrayU type holder + struct TypeHintBase{virtual ~TypeHintBase() = default;}; + + // This class holds type of initial GArray to be checked from GArrayU + template + struct TypeHint final : public TypeHintBase{}; + + // This class strips type information from GArray and makes it usable + // in the G-API graph compiler (expression unrolling, graph generation, etc). + // Part of GProtoArg. + class GAPI_EXPORTS GArrayU + { + public: + GArrayU(const GNode &n, std::size_t out); // Operation result constructor + + template + bool holds() const; // Check if was created from GArray + + GOrigin& priv(); // Internal use only + const GOrigin& priv() const; // Internal use only + + protected: + GArrayU(); // Default constructor + GArrayU(const detail::VectorRef& vref); // Constant value constructor + template friend class cv::GArray; // (available to GArray only) + + void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor + + template + void specifyType(); // Store type of initial GArray + + template + void storeKind(); + + void setKind(cv::detail::OpaqueKind); + + std::shared_ptr m_priv; + std::shared_ptr m_hint; + }; + + template + bool GArrayU::holds() const{ + GAPI_Assert(m_hint != nullptr); + using U = typename std::decay::type; + return dynamic_cast*>(m_hint.get()) != nullptr; + } + + template + void GArrayU::specifyType(){ + m_hint.reset(new TypeHint::type>); + } + + template + void GArrayU::storeKind(){ + setKind(cv::detail::GOpaqueTraits::kind); + } + + // This class represents a typed STL vector reference. + // Depending on origins, this reference may be either "just a" reference to + // an object created externally, OR actually own the underlying object + // (be value holder). + class BasicVectorRef + { + public: + // These fields are set by the derived class(es) + std::size_t m_elemSize = 0ul; + cv::GArrayDesc m_desc; + virtual ~BasicVectorRef() {} + + virtual void mov(BasicVectorRef &ref) = 0; + virtual const void* ptr() const = 0; + virtual std::size_t size() const = 0; + }; + + template class VectorRefT final: public BasicVectorRef + { + using empty_t = util::monostate; + using ro_ext_t = const std::vector *; + using rw_ext_t = std::vector *; + using rw_own_t = std::vector ; + util::variant m_ref; + + inline bool isEmpty() const { return util::holds_alternative(m_ref); } + inline bool isROExt() const { return util::holds_alternative(m_ref); } + inline bool isRWExt() const { return util::holds_alternative(m_ref); } + inline bool isRWOwn() const { return util::holds_alternative(m_ref); } + + void init(const std::vector* vec = nullptr) + { + m_elemSize = sizeof(T); + if (vec) m_desc = cv::descr_of(*vec); + } + + public: + VectorRefT() { init(); } + virtual ~VectorRefT() {} + + explicit VectorRefT(const std::vector& vec) : m_ref(&vec) { init(&vec); } + explicit VectorRefT(std::vector& vec) : m_ref(&vec) { init(&vec); } + explicit VectorRefT(std::vector&& vec) : m_ref(std::move(vec)) { init(&vec); } + + // Reset a VectorRefT. Called only for objects instantiated + // internally in G-API (e.g. temporary GArray's within a + // computation). Reset here means both initialization + // (creating an object) and reset (discarding its existing + // content before the next execution). Must never be called + // for external VectorRefTs. + void reset() + { + if (isEmpty()) + { + std::vector empty_vector; + m_desc = cv::descr_of(empty_vector); + m_ref = std::move(empty_vector); + GAPI_Assert(isRWOwn()); + } + else if (isRWOwn()) + { + util::get(m_ref).clear(); + } + else GAPI_Error("InternalError"); // shouldn't be called in *EXT modes + } + + // Obtain a WRITE reference to underlying object + // Used by CPU kernel API wrappers when a kernel execution frame + // is created + std::vector& wref() + { + GAPI_Assert(isRWExt() || isRWOwn()); + if (isRWExt()) return *util::get(m_ref); + if (isRWOwn()) return util::get(m_ref); + util::throw_error(std::logic_error("Impossible happened")); + } + + // Obtain a READ reference to underlying object + // Used by CPU kernel API wrappers when a kernel execution frame + // is created + const std::vector& rref() const + { + // ANY vector can be accessed for reading, even if it declared for + // output. Example -- a GComputation from [in] to [out1,out2] + // where [out2] is a result of operation applied to [out1]: + // + // GComputation boundary + // . . . . . . . + // . . + // [in] ----> foo() ----> [out1] + // . . : + // . . . .:. . . + // . V . + // . bar() ---> [out2] + // . . . . . . . . . . . . + // + if (isROExt()) return *util::get(m_ref); + if (isRWExt()) return *util::get(m_ref); + if (isRWOwn()) return util::get(m_ref); + util::throw_error(std::logic_error("Impossible happened")); + } + + virtual void mov(BasicVectorRef &v) override { + VectorRefT *tv = dynamic_cast*>(&v); + GAPI_Assert(tv != nullptr); + wref() = std::move(tv->wref()); + } + + virtual const void* ptr() const override { return &rref(); } + virtual std::size_t size() const override { return rref().size(); } + }; + + // This class strips type information from VectorRefT<> and makes it usable + // in the G-API executables (carrying run-time data/information to kernels). + // Part of GRunArg. + // Its methods are typed proxies to VectorRefT. + // VectorRef maintains "reference" semantics so two copies of VectoRef refer + // to the same underlying object. + // FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role + class VectorRef + { + std::shared_ptr m_ref; + cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN; + + template inline void check() const + { + GAPI_DbgAssert(dynamic_cast*>(m_ref.get()) != nullptr); + GAPI_Assert(sizeof(T) == m_ref->m_elemSize); + } + + public: + VectorRef() = default; + template explicit VectorRef(const std::vector& vec) + : m_ref(new VectorRefT(vec)) + , m_kind(GOpaqueTraits::kind) + {} + template explicit VectorRef(std::vector& vec) + : m_ref(new VectorRefT(vec)) + , m_kind(GOpaqueTraits::kind) + {} + template explicit VectorRef(std::vector&& vec) + : m_ref(new VectorRefT(std::move(vec))) + , m_kind(GOpaqueTraits::kind) + {} + + cv::detail::OpaqueKind getKind() const + { + return m_kind; + } + + template void reset() + { + if (!m_ref) m_ref.reset(new VectorRefT()); + check(); + storeKind(); + static_cast&>(*m_ref).reset(); + } + + template + void storeKind() + { + m_kind = cv::detail::GOpaqueTraits::kind; + } + + template std::vector& wref() + { + check(); + return static_cast&>(*m_ref).wref(); + } + + template const std::vector& rref() const + { + check(); + return static_cast&>(*m_ref).rref(); + } + + // Check if was created for/from std::vector + template bool holds() const + { + if (!m_ref) return false; + using U = typename std::decay::type; + return dynamic_cast*>(m_ref.get()) != nullptr; + } + + void mov(VectorRef &v) + { + m_ref->mov(*v.m_ref); + } + + cv::GArrayDesc descr_of() const + { + return m_ref->m_desc; + } + + std::size_t size() const + { + return m_ref->size(); + } + + // May be used to uniquely identify this object internally + const void *ptr() const { return m_ref->ptr(); } + }; + + // Helper (FIXME: work-around?) + // stripping G types to their host types + // like cv::GArray would still map to std::vector + // but not to std::vector +#if defined(GAPI_STANDALONE) +# define FLATTEN_NS cv::gapi::own +#else +# define FLATTEN_NS cv +#endif + template struct flatten_g; + template<> struct flatten_g { using type = FLATTEN_NS::Mat; }; + template<> struct flatten_g { using type = FLATTEN_NS::Scalar; }; + template struct flatten_g> { using type = std::vector; }; + template struct flatten_g { using type = T; }; +#undef FLATTEN_NS + // FIXME: the above mainly duplicates "ProtoToParam" thing from gtyped.hpp + // but I decided not to include gtyped here - probably worth moving that stuff + // to some common place? (DM) +} // namespace detail + +/** \addtogroup gapi_data_objects + * @{ + */ +/** + * @brief `cv::GArray` template class represents a list of objects + * of class `T` in the graph. + * + * `cv::GArray` describes a functional relationship between + * operations consuming and producing arrays of objects of class + * `T`. The primary purpose of `cv::GArray` is to represent a + * dynamic list of objects -- where the size of the list is not known + * at the graph construction or compile time. Examples include: corner + * and feature detectors (`cv::GArray`), object detection + * and tracking results (`cv::GArray`). Programmers can use + * their own types with `cv::GArray` in the custom operations. + * + * Similar to `cv::GScalar`, `cv::GArray` may be value-initialized + * -- in this case a graph-constant value is associated with the object. + * + * `GArray` is a virtual counterpart of `std::vector`, which is + * usually used to represent the `GArray` data in G-API during the + * execution. + * + * @sa `cv::GOpaque` + */ +template class GArray +{ +public: + // Host type (or Flat type) - the type this GArray is actually + // specified to. + /// @private + using HT = typename detail::flatten_g::type>::type; + + /** + * @brief Constructs a value-initialized `cv::GArray` + * + * `cv::GArray` objects may have their values + * be associated at graph construction time. It is useful when + * some operation has a `cv::GArray` input which doesn't change during + * the program execution, and is set only once. In this case, + * there is no need to declare such `cv::GArray` as a graph input. + * + * @note The value of `cv::GArray` may be overwritten by assigning some + * other `cv::GArray` to the object using `operator=` -- on the + * assignment, the old association or value is discarded. + * + * @param v a std::vector to associate with this + * `cv::GArray` object. Vector data is copied into the + * `cv::GArray` (no reference to the passed data is held). + */ + explicit GArray(const std::vector& v) // Constant value constructor + : m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); } + + /** + * @overload + * @brief Constructs a value-initialized `cv::GArray` + * + * @param v a std::vector to associate with this + * `cv::GArray` object. Vector data is moved into the `cv::GArray`. + */ + explicit GArray(std::vector&& v) // Move-constructor + : m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); } + + /** + * @brief Constructs an empty `cv::GArray` + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty `cv::GArray` is assigned to a result + * of some operation, it obtains a functional link to this + * operation (and is not empty anymore). + */ + GArray() { putDetails(); } // Empty constructor + + /// @private + explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor + : m_ref(ref) { putDetails(); } // (used by GCall, not for users) + + /// @private + detail::GArrayU strip() const { + return m_ref; + } + /// @private + static void VCtor(detail::VectorRef& vref) { + vref.reset(); + } + +private: + void putDetails() { + m_ref.setConstructFcn(&VCtor); + m_ref.specifyType(); // FIXME: to unify those 2 to avoid excessive dynamic_cast + m_ref.storeKind(); // + } + + detail::GArrayU m_ref; +}; + +/** @} */ + +} // namespace cv + +#endif // OPENCV_GAPI_GARRAY_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gasync_context.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gasync_context.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f49b59822d9d9acdf7f8e2a901786e0cf4b96da9 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gasync_context.hpp @@ -0,0 +1,63 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_GASYNC_CONTEXT_HPP +#define OPENCV_GAPI_GASYNC_CONTEXT_HPP + +#if !defined(GAPI_STANDALONE) +# include +#else // Without OpenCV +# include +#endif // !defined(GAPI_STANDALONE) + +#include + +namespace cv { +namespace gapi{ + +/** + * @brief This namespace contains experimental G-API functionality, + * functions or structures in this namespace are subjects to change or + * removal in the future releases. This namespace also contains + * functions which API is not stabilized yet. + */ +namespace wip { + +/** + * @brief A class to group async requests to cancel them in a single shot. + * + * GAsyncContext is passed as an argument to async() and async_apply() functions + */ + +class GAPI_EXPORTS GAsyncContext{ + std::atomic cancelation_requested = {false}; +public: + /** + * @brief Start cancellation process for an associated request. + * + * User still has to wait for each individual request (either via callback or according std::future object) to make sure it actually canceled. + * + * @return true if it was a first request to cancel the context + */ + bool cancel(); + + /** + * @brief Returns true if cancellation was requested for this context. + * + * @return true if cancellation was requested for this context + */ + bool isCanceled() const; +}; + +class GAPI_EXPORTS GAsyncCanceled : public std::exception { +public: + virtual const char* what() const noexcept CV_OVERRIDE; +}; +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif //OPENCV_GAPI_GASYNC_CONTEXT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcall.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcall.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8d1b8d60100c59a307d0e51667792f97dc7ed64a --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcall.hpp @@ -0,0 +1,78 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GCALL_HPP +#define OPENCV_GAPI_GCALL_HPP + +#include // GArg +#include // GMat +#include // GScalar +#include // GFrame +#include // GArray +#include // GOpaque + +namespace cv { + +struct GKernel; + +// The whole idea of this class is to represent an operation +// which is applied to arguments. This is part of public API, +// since it is what users should use to define kernel interfaces. + +class GAPI_EXPORTS GCall final +{ +public: + class Priv; + + explicit GCall(const GKernel &k); + ~GCall(); + + template + GCall& pass(Ts&&... args) + { + setArgs({cv::GArg(std::move(args))...}); + return *this; + } + + // A generic yield method - obtain a link to operator's particular GMat output + GMat yield (int output = 0); + GMatP yieldP (int output = 0); + GScalar yieldScalar(int output = 0); + GFrame yieldFrame (int output = 0); + + template GArray yieldArray(int output = 0) + { + return GArray(yieldArray(output)); + } + + template GOpaque yieldOpaque(int output = 0) + { + return GOpaque(yieldOpaque(output)); + } + + // Internal use only + Priv& priv(); + const Priv& priv() const; + + // GKernel and params can be modified, it's needed for infer, + // because information about output shapes doesn't exist in compile time + GKernel& kernel(); + cv::util::any& params(); + + void setArgs(std::vector &&args); + +protected: + std::shared_ptr m_priv; + + // Public versions return a typed array or opaque, those are implementation details + detail::GArrayU yieldArray(int output = 0); + detail::GOpaqueU yieldOpaque(int output = 0); +}; + +} // namespace cv + +#endif // OPENCV_GAPI_GCALL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcommon.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcommon.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c61110e4d5b5d1baed01852d0d9e2462bf511958 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcommon.hpp @@ -0,0 +1,309 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GCOMMON_HPP +#define OPENCV_GAPI_GCOMMON_HPP + +#include // std::hash +#include // std::vector +#include // decay + +#include + +#include +#include +#include +#include +#include +#include + +namespace cv { + +class GMat; // FIXME: forward declaration for GOpaqueTraits + +namespace detail +{ + // This is a trait-like structure to mark backend-specific compile arguments + // with tags + template struct CompileArgTag; + + // These structures are tags which separate kernels and transformations + struct KernelTag + {}; + struct TransformTag + {}; + + // This enum is utilized mostly by GArray and GOpaque to store and recognize their internal data + // types (aka Host type). Also it is widely used during serialization routine. + enum class OpaqueKind: int + { + CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization + CV_BOOL, // bool user G-API data + CV_INT, // int user G-API data + CV_INT64, // int64_t user G-API data + CV_DOUBLE, // double user G-API data + CV_FLOAT, // float user G-API data + CV_UINT64, // uint64_t user G-API data + CV_STRING, // std::string user G-API data + CV_POINT, // cv::Point user G-API data + CV_POINT2F, // cv::Point2f user G-API data + CV_POINT3F, // cv::Point3f user G-API data + CV_SIZE, // cv::Size user G-API data + CV_RECT, // cv::Rect user G-API data + CV_SCALAR, // cv::Scalar user G-API data + CV_MAT, // cv::Mat user G-API data + CV_DRAW_PRIM, // cv::gapi::wip::draw::Prim user G-API data + }; + + // Type traits helper which simplifies the extraction of kind from type + template struct GOpaqueTraits; + template struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT64; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_STRING; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT2F; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT3F; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; + template<> struct GOpaqueTraits + { static constexpr const OpaqueKind kind = OpaqueKind::CV_DRAW_PRIM; }; + using GOpaqueTraitsArrayTypes = std::tuple; + // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types + using GOpaqueTraitsOpaqueTypes = std::tuple; +} // namespace detail + +// This definition is here because it is reused by both public(?) and internal +// modules. Keeping it here wouldn't expose public details (e.g., API-level) +// to components which are internal and operate on a lower-level entities +// (e.g., compiler, backends). +// FIXME: merge with ArgKind? +// FIXME: replace with variant[format desc]? +enum class GShape: int +{ + GMAT, + GSCALAR, + GARRAY, + GOPAQUE, + GFRAME, +}; + +namespace gapi { +namespace s11n { +namespace detail { +template struct wrap_serialize; +} // namespace detail +} // namespace s11n +} // namespace gapi + + +struct GCompileArg; + +namespace detail { + template + using is_compile_arg = std::is_same::type>; +} // namespace detail + +// CompileArg is an unified interface over backend-specific compilation +// information +// FIXME: Move to a separate file? +/** \addtogroup gapi_compile_args + * @{ + * + * @brief Compilation arguments: data structures controlling the + * compilation process + * + * G-API comes with a number of graph compilation options which can be + * passed to cv::GComputation::apply() or + * cv::GComputation::compile(). Known compilation options are listed + * in this page, while extra backends may introduce their own + * compilation options (G-API transparently accepts _everything_ which + * can be passed to cv::compile_args(), it depends on underlying + * backends if an option would be interpreted or not). + * + * For example, if an example computation is executed like this: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_decl_apply + * + * Extra parameter specifying which kernels to compile with can be + * passed like this: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp apply_with_param + */ + +/** + * @brief Represents an arbitrary compilation argument. + * + * Any value can be wrapped into cv::GCompileArg, but only known ones + * (to G-API or its backends) can be interpreted correctly. + * + * Normally objects of this class shouldn't be created manually, use + * cv::compile_args() function which automatically wraps everything + * passed in (a variadic template parameter pack) into a vector of + * cv::GCompileArg objects. + */ +struct GCompileArg +{ +public: + // NB: Required for pythnon bindings + GCompileArg() = default; + + std::string tag; + + // FIXME: use decay in GArg/other trait-based wrapper before leg is shot! + template::value, int>::type = 0> + explicit GCompileArg(T &&t) + : tag(detail::CompileArgTag::type>::tag()) + , serializeF(cv::gapi::s11n::detail::has_S11N_spec::value ? + &cv::gapi::s11n::detail::wrap_serialize::serialize : + nullptr) + , arg(t) + { + } + + template T& get() + { + return util::any_cast(arg); + } + + template const T& get() const + { + return util::any_cast(arg); + } + + void serialize(cv::gapi::s11n::IOStream& os) const + { + if (serializeF) + { + serializeF(os, *this); + } + } + +private: + std::function serializeF; + util::any arg; +}; + +using GCompileArgs = std::vector; + +inline cv::GCompileArgs& operator += ( cv::GCompileArgs &lhs, + const cv::GCompileArgs &rhs) +{ + lhs.reserve(lhs.size() + rhs.size()); + lhs.insert(lhs.end(), rhs.begin(), rhs.end()); + return lhs; +} + +/** + * @brief Wraps a list of arguments (a parameter pack) into a vector of + * compilation arguments (cv::GCompileArg). + */ +template GCompileArgs compile_args(Ts&&... args) +{ + return GCompileArgs{ GCompileArg(args)... }; +} + +namespace gapi +{ +/** + * @brief Retrieves particular compilation argument by its type from + * cv::GCompileArgs + */ +template +inline cv::util::optional getCompileArg(const cv::GCompileArgs &args) +{ + for (auto &compile_arg : args) + { + if (compile_arg.tag == cv::detail::CompileArgTag::tag()) + { + return cv::util::optional(compile_arg.get()); + } + } + return cv::util::optional(); +} + +namespace s11n { +namespace detail { +template struct wrap_serialize +{ + static void serialize(IOStream& os, const GCompileArg& arg) + { + using DT = typename std::decay::type; + S11N

::serialize(os, arg.get
()); + } +}; +} // namespace detail +} // namespace s11n +} // namespace gapi + +/** @} gapi_compile_args */ + +/** + * @brief Ask G-API to dump compiled graph in Graphviz format under + * the given file name. + * + * Specifies a graph dump path (path to .dot file to be generated). + * G-API will dump a .dot file under specified path during a + * compilation process if this flag is passed. + */ +struct graph_dump_path +{ + std::string m_dump_path; +}; + +/** + * @brief Ask G-API to use threaded executor when cv::GComputation + * is compiled via cv::GComputation::compile method. + * + * Specifies a number of threads that should be used by executor. + */ +struct GAPI_EXPORTS use_threaded_executor +{ + use_threaded_executor(); + explicit use_threaded_executor(const uint32_t nthreads); + + uint32_t num_threads; +}; + +namespace detail +{ + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.graph_dump_path"; } + }; + + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.threaded_executor"; } + }; +} + +} // namespace cv + +// std::hash overload for GShape +namespace std +{ +template<> struct hash +{ + size_t operator() (cv::GShape sh) const + { + return std::hash()(static_cast(sh)); + } +}; +} // namespace std + + +#endif // OPENCV_GAPI_GCOMMON_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ac36783d6215c1d38134685219a86523bd45dca1 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled.hpp @@ -0,0 +1,232 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GCOMPILED_HPP +#define OPENCV_GAPI_GCOMPILED_HPP + +#include + +#include +#include +#include + +namespace cv { + +// This class represents a compiled computation. +// In theory (and ideally), it can be used w/o the rest of APIs. +// In theory (and ideally), it can be serialized/deserialized. +// It can enable scenarious like deployment to an autonomous devince, FuSa, etc. +// +// Currently GCompiled assumes all GMats you used to pass data to G-API +// are valid and not destroyed while you use a GCompiled object. +// +// FIXME: In future, there should be a way to name I/O objects and specify it +// to GCompiled externally (for example, when it is loaded on the target system). + +/** + * \addtogroup gapi_main_classes + * @{ + */ +/** + * @brief Represents a compiled computation (graph). Can only be used + * with image / data formats & resolutions it was compiled for, with + * some exceptions. + * + * This class represents a product of graph compilation (calling + * cv::GComputation::compile()). Objects of this class actually do + * data processing, and graph execution is incapsulated into objects + * of this class. Execution model itself depends on kernels and + * backends which were using during the compilation, see @ref + * gapi_compile_args for details. + * + * In a general case, GCompiled objects can be applied to data only in + * that formats/resolutions they were compiled for (see @ref + * gapi_meta_args). However, if the underlying backends allow, a + * compiled object can be _reshaped_ to handle data (images) of + * different resolution, though formats and types must remain the same. + * + * GCompiled is very similar to `std::function<>` in its semantics -- + * running it looks like a function call in the user code. + * + * At the moment, GCompiled objects are not reentrant -- generally, + * the objects are stateful since graph execution itself is a stateful + * process and this state is now maintained in GCompiled's own memory + * (not on the process stack). + * + * At the same time, two different GCompiled objects produced from the + * single cv::GComputation are completely independent and can be used + * concurrently. + * + * @sa GStreamingCompiled + */ +class GAPI_EXPORTS GCompiled +{ +public: + /// @private + class GAPI_EXPORTS Priv; + + /** + * @brief Constructs an empty object + */ + GCompiled(); + + /** + * @brief Run the compiled computation, a generic version. + * + * @param ins vector of inputs to process. + * @param outs vector of outputs to produce. + * + * Input/output vectors must have the same number of elements as + * defined in the cv::GComputation protocol (at the moment of its + * construction). Shapes of elements also must conform to protocol + * (e.g. cv::Mat needs to be passed where cv::GMat has been + * declared as input, and so on). Run-time exception is generated + * otherwise. + * + * Objects in output vector may remain empty (like cv::Mat) -- + * G-API will automatically initialize output objects to proper formats. + * + * @note Don't construct GRunArgs/GRunArgsP objects manually, use + * cv::gin()/cv::gout() wrappers instead. + */ + void operator() (GRunArgs &&ins, GRunArgsP &&outs); // Generic arg-to-arg +#if !defined(GAPI_STANDALONE) + + /** + * @brief Execute an unary computation + * + * @overload + * @param in input cv::Mat for unary computation + * @param out output cv::Mat for unary computation + * process. + */ + void operator() (cv::Mat in, cv::Mat &out); // Unary overload + + /** + * @brief Execute an unary computation + * + * @overload + * @param in input cv::Mat for unary computation + * @param out output cv::Scalar for unary computation + * process. + */ + void operator() (cv::Mat in, cv::Scalar &out); // Unary overload (scalar) + + /** + * @brief Execute a binary computation + * + * @overload + * @param in1 first input cv::Mat for binary computation + * @param in2 second input cv::Mat for binary computation + * @param out output cv::Mat for binary computation + * process. + */ + void operator() (cv::Mat in1, cv::Mat in2, cv::Mat &out); // Binary overload + + /** + * @brief Execute an binary computation + * + * @overload + * @param in1 first input cv::Mat for binary computation + * @param in2 second input cv::Mat for binary computation + * @param out output cv::Scalar for binary computation + * process. + */ + void operator() (cv::Mat in1, cv::Mat in2, cv::Scalar &out); // Binary overload (scalar) + + /** + * @brief Execute a computation with arbitrary number of + * inputs/outputs. + * + * @overload + * @param ins vector of input cv::Mat objects to process by the + * computation. + * @param outs vector of output cv::Mat objects to produce by the + * computation. + * + * Numbers of elements in ins/outs vectors must match numbers of + * inputs/outputs which were used to define the source GComputation. + */ + void operator() (const std::vector &ins, // Compatibility overload + const std::vector &outs); +#endif // !defined(GAPI_STANDALONE) + /// @private + Priv& priv(); + + /** + * @brief Check if compiled object is valid (non-empty) + * + * @return true if the object is runnable (valid), false otherwise + */ + explicit operator bool () const; + + /** + * @brief Vector of metadata this graph was compiled for. + * + * @return Unless _reshape_ is not supported, return value is the + * same vector which was passed to cv::GComputation::compile() to + * produce this compiled object. Otherwise, it is the latest + * metadata vector passed to reshape() (if that call was + * successful). + */ + const GMetaArgs& metas() const; // Meta passed to compile() + + /** + * @brief Vector of metadata descriptions of graph outputs + * + * @return vector with formats/resolutions of graph's output + * objects, auto-inferred from input metadata vector by + * operations which form this computation. + * + * @note GCompiled objects produced from the same + * cv::GComputiation graph with different input metas may return + * different values in this vector. + */ + const GMetaArgs& outMetas() const; + + /** + * @brief Check if the underlying backends support reshape or not. + * + * @return true if supported, false otherwise. + */ + bool canReshape() const; + + /** + * @brief Reshape a compiled graph to support new image + * resolutions. + * + * Throws an exception if an error occurs. + * + * @param inMetas new metadata to reshape on. Vector size and + * metadata shapes must match the computation's protocol. + * @param args compilation arguments to use. + */ + // FIXME: Why it requires compile args? + void reshape(const GMetaArgs& inMetas, const GCompileArgs& args); + + /** + * @brief Prepare inner kernels states for a new video-stream. + * + * GCompiled objects may be used to process video streams frame by frame. + * In this case, a GCompiled is called on every image frame individually. + * Starting OpenCV 4.4, some kernels in the graph may have their internal + * states (see GAPI_OCV_KERNEL_ST for the OpenCV backend). + * In this case, if user starts processing another video stream with + * this GCompiled, this method needs to be called to let kernels re-initialize + * their internal states to a new video stream. + */ + void prepareForNewStream(); + +protected: + /// @private + std::shared_ptr m_priv; +}; +/** @} */ + +} + +#endif // OPENCV_GAPI_GCOMPILED_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled_async.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled_async.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a0c2917d6a85b84c4c275a5bf7fed7d9918a438f --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompiled_async.hpp @@ -0,0 +1,73 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + + +#ifndef OPENCV_GAPI_GCOMPILED_ASYNC_HPP +#define OPENCV_GAPI_GCOMPILED_ASYNC_HPP + +#include //for std::future +#include //for std::exception_ptr +#include //for std::function +#include +#include + +namespace cv { + //fwd declaration + class GCompiled; + +namespace gapi{ +namespace wip { + class GAsyncContext; + /** + These functions asynchronously (i.e. probably on a separate thread of execution) call GCompiled::operator() member function of their first argument with copies of rest of arguments (except callback) passed in. + The difference between the function is the way to get the completion notification (via callback or a waiting on std::future object) + If exception is occurred during execution of apply it is transferred to the callback (via function parameter) or passed to future (and will be thrown on call to std::future::get) + + N.B. : + Input arguments are copied on call to async function (actually on call to cv::gin) and thus do not have to outlive the actual completion of asynchronous activity. + While output arguments are "captured" by reference(pointer) and therefore _must_ outlive the asynchronous activity + (i.e. live at least until callback is called or future is unblocked) + + @param gcmpld Compiled computation (graph) to start asynchronously + @param callback Callback to be called when execution of gcmpld is done + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + */ + GAPI_EXPORTS void async(GCompiled& gcmpld, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs); + + /** @overload + @param gcmpld Compiled computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcmpld is done + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @param ctx Context this request belongs to + @see async GAsyncContext + */ + GAPI_EXPORTS void async(GCompiled& gcmpld, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GAsyncContext& ctx); + + /** @overload + @param gcmpld Compiled computation (graph) to run asynchronously + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @return std::future object to wait for completion of async operation + @see async + */ + GAPI_EXPORTS std::future async(GCompiled& gcmpld, GRunArgs &&ins, GRunArgsP &&outs); + + /** + @param gcmpld Compiled computation (graph) to run asynchronously + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @param ctx Context this request belongs to + @return std::future object to wait for completion of async operation + @see async GAsyncContext + */ + GAPI_EXPORTS std::future async(GCompiled& gcmpld, GRunArgs &&ins, GRunArgsP &&outs, GAsyncContext& ctx); +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_GCOMPILED_ASYNC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompoundkernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompoundkernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..df0ce340457a2c3465fb3ad10d9bc3dc73b3fe2b --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcompoundkernel.hpp @@ -0,0 +1,139 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2019 Intel Corporation + + +#ifndef OPENCV_GAPI_GCOMPOUNDKERNEL_HPP +#define OPENCV_GAPI_GCOMPOUNDKERNEL_HPP + +#include +#include +#include +#include + +namespace cv { +namespace gapi +{ +namespace compound +{ + // FIXME User does not need to know about this function + // Needs that user may define compound kernels(as cpu kernels) + GAPI_EXPORTS cv::gapi::GBackend backend(); +} // namespace compound +} // namespace gapi + +namespace detail +{ + +struct GCompoundContext +{ + explicit GCompoundContext(const GArgs& in_args); + template + const T& inArg(int input) { return m_args.at(input).get(); } + + GArgs m_args; + GArgs m_results; +}; + +class GAPI_EXPORTS GCompoundKernel +{ +// Compound kernel must use all of it's inputs +public: + using F = std::function; + + explicit GCompoundKernel(const F& f); + void apply(GCompoundContext& ctx); + +protected: + F m_f; +}; + +template struct get_compound_in +{ + static T get(GCompoundContext &ctx, int idx) { return ctx.inArg(idx); } +}; + +template struct get_compound_in> +{ + static cv::GArray get(GCompoundContext &ctx, int idx) + { + auto array = cv::GArray(); + ctx.m_args[idx] = GArg(array); + return array; + } +}; + +template struct get_compound_in> +{ + static cv::GOpaque get(GCompoundContext &ctx, int idx) + { + auto opaq = cv::GOpaque(); + ctx.m_args[idx] = GArg(opaq); + return opaq; + } +}; + +template<> struct get_compound_in +{ + static cv::GMatP get(GCompoundContext &ctx, int idx) + { + auto mat = cv::GMatP(); + ctx.m_args[idx] = GArg(mat); + return mat; + } +}; + +template +struct GCompoundCallHelper; + +template +struct GCompoundCallHelper, std::tuple > +{ + template + static void expand_impl(GCompoundContext &ctx, detail::Seq, detail::Seq) + { + auto result = Impl::expand(get_compound_in::get(ctx, IIs)...); + auto tuple_return = tuple_wrap_helper::get(std::move(result)); + ctx.m_results = { cv::GArg(std::get(tuple_return))... }; + } + + static void expand(GCompoundContext &ctx) + { + expand_impl(ctx, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } +}; + +template +class GCompoundKernelImpl: public cv::detail::GCompoundCallHelper, + public cv::detail::KernelTag +{ + using P = cv::detail::GCompoundCallHelper; + +public: + using API = K; + + static cv::gapi::GBackend backend() { return cv::gapi::compound::backend(); } + static GCompoundKernel kernel() { return GCompoundKernel(&P::expand); } +}; + +} // namespace detail + + +/** + * Declares a new compound kernel. See this + * [documentation chapter](@ref gapi_kernel_compound) + * on compound kernels for more details. + * + * @param Name type name for new kernel + * @param API the interface this kernel implements + */ +#define GAPI_COMPOUND_KERNEL(Name, API) \ + struct Name: public cv::detail::GCompoundKernelImpl + +} // namespace cv + +#endif // OPENCV_GAPI_GCOMPOUNDKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..196eb37c6b4ff74b934b82db6188c014669c5ab5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation.hpp @@ -0,0 +1,581 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GCOMPUTATION_HPP +#define OPENCV_GAPI_GCOMPUTATION_HPP + +#include + +#include +#include +#include +#include +#include +#include + +namespace cv { + +namespace detail +{ + // FIXME: move to algorithm, cover with separate tests + // FIXME: replace with O(1) version (both memory and compilation time) + template + struct last_type; + + template + struct last_type { using type = T;}; + + template + struct last_type { using type = typename last_type::type; }; + + template + using last_type_t = typename last_type::type; +} + +// Forward-declare the serialization objects +namespace gapi { +namespace s11n { + struct IIStream; + struct IOStream; +} // namespace s11n +} // namespace gapi + +/** + * \addtogroup gapi_main_classes + * @{ + * + * @brief G-API classes for constructed and compiled graphs. + */ + +/** + * @brief GComputation class represents a captured computation + * graph. GComputation objects form boundaries for expression code + * user writes with G-API, allowing to compile and execute it. + * + * G-API computations are defined with input/output data + * objects. G-API will track automatically which operations connect + * specified outputs to the inputs, forming up a call graph to be + * executed. The below example expresses calculation of Sobel operator + * for edge detection (\f$G = \sqrt{G_x^2 + G_y^2}\f$): + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_def + * + * Full pipeline can be now captured with this object declaration: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_cap_full + * + * Input/output data objects on which a call graph should be + * reconstructed are passed using special wrappers cv::GIn and + * cv::GOut. G-API will track automatically which operations form a + * path from inputs to outputs and build the execution graph appropriately. + * + * Note that cv::GComputation doesn't take ownership on data objects + * it is defined. Moreover, multiple GComputation objects may be + * defined on the same expressions, e.g. a smaller pipeline which + * expects that image gradients are already pre-calculated may be + * defined like this: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_cap_sub + * + * The resulting graph would expect two inputs and produce one + * output. In this case, it doesn't matter if gx/gy data objects are + * results of cv::gapi::Sobel operators -- G-API will stop unrolling + * expressions and building the underlying graph one reaching this + * data objects. + * + * The way how GComputation is defined is important as its definition + * specifies graph _protocol_ -- the way how the graph should be + * used. Protocol is defined by number of inputs, number of outputs, + * and shapes of inputs and outputs. + * + * In the above example, sobelEdge expects one Mat on input and + * produces one Mat; while sobelEdgeSub expects two Mats on input and + * produces one Mat. GComputation's protocol defines how other + * computation methods should be used -- cv::GComputation::compile() and + * cv::GComputation::apply(). For example, if a graph is defined on + * two GMat inputs, two cv::Mat objects have to be passed to apply() + * for execution. GComputation checks protocol correctness in runtime + * so passing a different number of objects in apply() or passing + * cv::Scalar instead of cv::Mat there would compile well as a C++ + * source but raise an exception in run-time. G-API also comes with a + * typed wrapper cv::GComputationT<> which introduces this type-checking in + * compile-time. + * + * cv::GComputation itself is a thin object which just captures what + * the graph is. The compiled graph (which actually process data) is + * represented by class GCompiled. Use compile() method to generate a + * compiled graph with given compile options. cv::GComputation can + * also be used to process data with implicit graph compilation + * on-the-fly, see apply() for details. + * + * GComputation is a reference-counted object -- once defined, all its + * copies will refer to the same instance. + * + * @sa GCompiled + */ +class GAPI_EXPORTS_W GComputation +{ +public: + class Priv; + typedef std::function Generator; + + // Various constructors enable different ways to define a computation: ///// + // 1. Generic constructors + /** + * @brief Define a computation using a generator function. + * + * Graph can be defined in-place directly at the moment of its + * construction with a lambda: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_gen + * + * This may be useful since all temporary objects (cv::GMats) and + * namespaces can be localized to scope of lambda, without + * contaminating the parent scope with probably unnecessary objects + * and information. + * + * @param gen generator function which returns a cv::GComputation, + * see Generator. + */ + GComputation(const Generator& gen); // Generator + // overload + + /** + * @brief Generic GComputation constructor. + * + * Constructs a new graph with a given protocol, specified as a + * flow of operations connecting input/output objects. Throws if + * the passed boundaries are invalid, e.g. if there's no + * functional dependency (path) between given outputs and inputs. + * + * @param ins Input data vector. + * @param outs Output data vector. + * + * @note Don't construct GProtoInputArgs/GProtoOutputArgs objects + * directly, use cv::GIn()/cv::GOut() wrapper functions instead. + * + * @sa @ref gapi_data_objects + */ + GAPI_WRAP GComputation(GProtoInputArgs &&ins, + GProtoOutputArgs &&outs); // Arg-to-arg overload + + // 2. Syntax sugar and compatibility overloads + /** + * @brief Defines an unary (one input -- one output) computation + * + * @overload + * @param in input GMat of the defined unary computation + * @param out output GMat of the defined unary computation + */ + GAPI_WRAP GComputation(GMat in, GMat out); // Unary overload + + /** + * @brief Defines an unary (one input -- one output) computation + * + * @overload + * @param in input GMat of the defined unary computation + * @param out output GScalar of the defined unary computation + */ + GAPI_WRAP GComputation(GMat in, GScalar out); // Unary overload (scalar) + + /** + * @brief Defines a binary (two inputs -- one output) computation + * + * @overload + * @param in1 first input GMat of the defined binary computation + * @param in2 second input GMat of the defined binary computation + * @param out output GMat of the defined binary computation + */ + GAPI_WRAP GComputation(GMat in1, GMat in2, GMat out); // Binary overload + + /** + * @brief Defines a binary (two inputs -- one output) computation + * + * @overload + * @param in1 first input GMat of the defined binary computation + * @param in2 second input GMat of the defined binary computation + * @param out output GScalar of the defined binary computation + */ + GComputation(GMat in1, GMat in2, GScalar out); // Binary + // overload + // (scalar) + + /** + * @brief Defines a computation with arbitrary input/output number. + * + * @overload + * @param ins vector of inputs GMats for this computation + * @param outs vector of outputs GMats for this computation + * + * Use this overload for cases when number of computation + * inputs/outputs is not known in compile-time -- e.g. when graph + * is programmatically generated to build an image pyramid with + * the given number of levels, etc. + */ + GComputation(const std::vector &ins, // Compatibility overload + const std::vector &outs); + + // Various versions of apply(): //////////////////////////////////////////// + // 1. Generic apply() + /** + * @brief Compile graph on-the-fly and immediately execute it on + * the inputs data vectors. + * + * Number of input/output data objects must match GComputation's + * protocol, also types of host data objects (cv::Mat, cv::Scalar) + * must match the shapes of data objects from protocol (cv::GMat, + * cv::GScalar). If there's a mismatch, a run-time exception will + * be generated. + * + * Internally, a cv::GCompiled object is created for the given + * input format configuration, which then is executed on the input + * data immediately. cv::GComputation caches compiled objects + * produced within apply() -- if this method would be called next + * time with the same input parameters (image formats, image + * resolution, etc), the underlying compiled graph will be reused + * without recompilation. If new metadata doesn't match the cached + * one, the underlying compiled graph is regenerated. + * + * @note compile() always triggers a compilation process and + * produces a new GCompiled object regardless if a similar one has + * been cached via apply() or not. + * + * @param ins vector of input data to process. Don't create + * GRunArgs object manually, use cv::gin() wrapper instead. + * @param outs vector of output data to fill results in. cv::Mat + * objects may be empty in this vector, G-API will automatically + * initialize it with the required format & dimensions. Don't + * create GRunArgsP object manually, use cv::gout() wrapper instead. + * @param args a list of compilation arguments to pass to the + * underlying compilation process. Don't create GCompileArgs + * object manually, use cv::compile_args() wrapper instead. + * + * @sa @ref gapi_data_objects, @ref gapi_compile_args + */ + void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload + + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP GRunArgs apply(const cv::detail::ExtractArgsCallback &callback, + GCompileArgs &&args = {}); + + /// @private -- Exclude this function from OpenCV documentation + void apply(const std::vector& ins, // Compatibility overload + const std::vector& outs, + GCompileArgs &&args = {}); + + // 2. Syntax sugar and compatibility overloads +#if !defined(GAPI_STANDALONE) + /** + * @brief Execute an unary computation (with compilation on the fly) + * + * @overload + * @param in input cv::Mat for unary computation + * @param out output cv::Mat for unary computation + * @param args compilation arguments for underlying compilation + * process. + */ + void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload + + /** + * @brief Execute an unary computation (with compilation on the fly) + * + * @overload + * @param in input cv::Mat for unary computation + * @param out output cv::Scalar for unary computation + * @param args compilation arguments for underlying compilation + * process. + */ + void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar) + + /** + * @brief Execute a binary computation (with compilation on the fly) + * + * @overload + * @param in1 first input cv::Mat for binary computation + * @param in2 second input cv::Mat for binary computation + * @param out output cv::Mat for binary computation + * @param args compilation arguments for underlying compilation + * process. + */ + void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload + + /** + * @brief Execute an binary computation (with compilation on the fly) + * + * @overload + * @param in1 first input cv::Mat for binary computation + * @param in2 second input cv::Mat for binary computation + * @param out output cv::Scalar for binary computation + * @param args compilation arguments for underlying compilation + * process. + */ + void apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompileArgs &&args = {}); // Binary overload (scalar) + + /** + * @brief Execute a computation with arbitrary number of + * inputs/outputs (with compilation on-the-fly). + * + * @overload + * @param ins vector of input cv::Mat objects to process by the + * computation. + * @param outs vector of output cv::Mat objects to produce by the + * computation. + * @param args compilation arguments for underlying compilation + * process. + * + * Numbers of elements in ins/outs vectors must match numbers of + * inputs/outputs which were used to define this GComputation. + */ + void apply(const std::vector& ins, // Compatibility overload + std::vector& outs, + GCompileArgs &&args = {}); +#endif // !defined(GAPI_STANDALONE) + // Various versions of compile(): ////////////////////////////////////////// + // 1. Generic compile() - requires metas to be passed as vector + /** + * @brief Compile the computation for specific input format(s). + * + * This method triggers compilation process and produces a new + * GCompiled object which then can process data of the given + * format. Passing data with different format to the compiled + * computation will generate a run-time exception. + * + * @param in_metas vector of input metadata configuration. Grab + * metadata from real data objects (like cv::Mat or cv::Scalar) + * using cv::descr_of(), or create it on your own. + * @param args compilation arguments for this compilation + * process. Compilation arguments directly affect what kind of + * executable object would be produced, e.g. which kernels (and + * thus, devices) would be used to execute computation. + * + * @return GCompiled, an executable computation compiled + * specifically for the given input parameters. + * + * @sa @ref gapi_compile_args + */ + GCompiled compile(GMetaArgs &&in_metas, GCompileArgs &&args = {}); + + // 2. Syntax sugar - variadic list of metas, no extra compile args + // FIXME: SFINAE looks ugly in the generated documentation + /** + * @overload + * + * Takes a variadic parameter pack with metadata + * descriptors for which a compiled object needs to be produced. + * + * @return GCompiled, an executable computation compiled + * specifically for the given input parameters. + */ + template + auto compile(const Ts&... metas) -> + typename std::enable_if::value, GCompiled>::type + { + return compile(GMetaArgs{GMetaArg(metas)...}, GCompileArgs()); + } + + // 3. Syntax sugar - variadic list of metas, extra compile args + // (seems optional parameters don't work well when there's an variadic template + // comes first) + // + // Ideally it should look like: + // + // template + // GCompiled compile(const Ts&... metas, GCompileArgs &&args) + // + // But not all compilers can handle this (and seems they shouldn't be able to). + // FIXME: SFINAE looks ugly in the generated documentation + /** + * @overload + * + * Takes a variadic parameter pack with metadata + * descriptors for which a compiled object needs to be produced, + * followed by GCompileArgs object representing compilation + * arguments for this process. + * + * @return GCompiled, an executable computation compiled + * specifically for the given input parameters. + */ + template + auto compile(const Ts&... meta_and_compile_args) -> + typename std::enable_if::value + && std::is_same >::value, + GCompiled>::type + { + //FIXME: wrapping meta_and_compile_args into a tuple to unwrap them inside a helper function is the overkill + return compile(std::make_tuple(meta_and_compile_args...), + typename detail::MkSeq::type()); + } + + + // FIXME: Document properly in the Doxygen format + // Video-oriented pipeline compilation: + // 1. A generic version + /** + * @brief Compile the computation for streaming mode. + * + * This method triggers compilation process and produces a new + * GStreamingCompiled object which then can process video stream + * data of the given format. Passing a stream in a different + * format to the compiled computation will generate a run-time + * exception. + * + * @param in_metas vector of input metadata configuration. Grab + * metadata from real data objects (like cv::Mat or cv::Scalar) + * using cv::descr_of(), or create it on your own. + * + * @param args compilation arguments for this compilation + * process. Compilation arguments directly affect what kind of + * executable object would be produced, e.g. which kernels (and + * thus, devices) would be used to execute computation. + * + * @return GStreamingCompiled, a streaming-oriented executable + * computation compiled specifically for the given input + * parameters. + * + * @sa @ref gapi_compile_args + */ + GAPI_WRAP GStreamingCompiled compileStreaming(GMetaArgs &&in_metas, GCompileArgs &&args = {}); + + /** + * @brief Compile the computation for streaming mode. + * + * This method triggers compilation process and produces a new + * GStreamingCompiled object which then can process video stream + * data in any format. Underlying mechanisms will be adjusted to + * every new input video stream automatically, but please note that + * _not all_ existing backends support this (see reshape()). + * + * @param args compilation arguments for this compilation + * process. Compilation arguments directly affect what kind of + * executable object would be produced, e.g. which kernels (and + * thus, devices) would be used to execute computation. + * + * @return GStreamingCompiled, a streaming-oriented executable + * computation compiled for any input image format. + * + * @sa @ref gapi_compile_args + */ + GAPI_WRAP GStreamingCompiled compileStreaming(GCompileArgs &&args = {}); + + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP GStreamingCompiled compileStreaming(const cv::detail::ExtractMetaCallback &callback, + GCompileArgs &&args = {}); + + // 2. Direct metadata version + /** + * @overload + * + * Takes a variadic parameter pack with metadata + * descriptors for which a compiled object needs to be produced. + * + * @return GStreamingCompiled, a streaming-oriented executable + * computation compiled specifically for the given input + * parameters. + */ + template + auto compileStreaming(const Ts&... metas) -> + typename std::enable_if::value, GStreamingCompiled>::type + { + return compileStreaming(GMetaArgs{GMetaArg(metas)...}, GCompileArgs()); + } + + // 2. Direct metadata + compile arguments version + /** + * @overload + * + * Takes a variadic parameter pack with metadata + * descriptors for which a compiled object needs to be produced, + * followed by GCompileArgs object representing compilation + * arguments for this process. + * + * @return GStreamingCompiled, a streaming-oriented executable + * computation compiled specifically for the given input + * parameters. + */ + template + auto compileStreaming(const Ts&... meta_and_compile_args) -> + typename std::enable_if::value + && std::is_same >::value, + GStreamingCompiled>::type + { + //FIXME: wrapping meta_and_compile_args into a tuple to unwrap them inside a helper function is the overkill + return compileStreaming(std::make_tuple(meta_and_compile_args...), + typename detail::MkSeq::type()); + } + + // Internal use only + /// @private + Priv& priv(); + /// @private + const Priv& priv() const; + /// @private + explicit GComputation(cv::gapi::s11n::IIStream &); + /// @private + void serialize(cv::gapi::s11n::IOStream &) const; + +protected: + + // 4. Helper methods for (3) + /// @private + template + GCompiled compile(const std::tuple &meta_and_compile_args, detail::Seq) + { + GMetaArgs meta_args = {GMetaArg(std::get(meta_and_compile_args))...}; + GCompileArgs comp_args = std::get(meta_and_compile_args); + return compile(std::move(meta_args), std::move(comp_args)); + } + template + GStreamingCompiled compileStreaming(const std::tuple &meta_and_compile_args, detail::Seq) + { + GMetaArgs meta_args = {GMetaArg(std::get(meta_and_compile_args))...}; + GCompileArgs comp_args = std::get(meta_and_compile_args); + return compileStreaming(std::move(meta_args), std::move(comp_args)); + } + void recompile(GMetaArgs&& in_metas, GCompileArgs &&args); + /// @private + std::shared_ptr m_priv; +}; +/** @} */ + +namespace gapi +{ + // FIXME: all these standalone functions need to be added to some + // common documentation section + /** + * @brief Define an tagged island (subgraph) within a computation. + * + * Declare an Island tagged with `name` and defined from `ins` to `outs` + * (exclusively, as ins/outs are data objects, and regioning is done on + * operations level). + * Throws if any operation between `ins` and `outs` are already assigned + * to another island. + * + * Islands allow to partition graph into subgraphs, fine-tuning + * the way it is scheduled by the underlying executor. + * + * @param name name of the Island to create + * @param ins vector of input data objects where the subgraph + * begins + * @param outs vector of output data objects where the subgraph + * ends. + * + * The way how an island is defined is similar to how + * cv::GComputation is defined on input/output data objects. + * Same rules apply here as well -- if there's no functional + * dependency between inputs and outputs or there's not enough + * input data objects were specified to properly calculate all + * outputs, an exception is thrown. + * + * Use cv::GIn() / cv::GOut() to specify input/output vectors. + */ + void GAPI_EXPORTS island(const std::string &name, + GProtoInputArgs &&ins, + GProtoOutputArgs &&outs); +} // namespace gapi + +} // namespace cv +#endif // OPENCV_GAPI_GCOMPUTATION_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation_async.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation_async.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8af603efead4656c8b8eba64a80625c1c6a02cae --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gcomputation_async.hpp @@ -0,0 +1,69 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_GCOMPUTATION_ASYNC_HPP +#define OPENCV_GAPI_GCOMPUTATION_ASYNC_HPP + + +#include //for std::future +#include //for std::exception_ptr +#include //for std::function +#include //for GRunArgs, GRunArgsP +#include //for GCompileArgs +#include + + +namespace cv { + //fwd declaration + class GComputation; +namespace gapi { +namespace wip { + class GAsyncContext; + /** In contrast to async() functions, these do call GComputation::apply() member function of the GComputation passed in. + + @param gcomp Computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcomp is done + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @see async + */ + GAPI_EXPORTS void async_apply(GComputation& gcomp, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcomp is done + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @param ctx Context this request belongs to + @see async_apply async GAsyncContext + */ + GAPI_EXPORTS void async_apply(GComputation& gcomp, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args, GAsyncContext& ctx); + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @return std::future object to wait for completion of async operation + @see async_apply async + */ + GAPI_EXPORTS std::future async_apply(GComputation& gcomp, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @param ctx Context this request belongs to + @return std::future object to wait for completion of async operation + @see async_apply async GAsyncContext + */ + GAPI_EXPORTS std::future async_apply(GComputation& gcomp, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args, GAsyncContext& ctx); +} // namespace wip +} // namespace gapi +} // namespace cv + + +#endif //OPENCV_GAPI_GCOMPUTATION_ASYNC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gframe.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gframe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..54fb30789e33fe717235d5f82f47a28fbe7a37e3 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gframe.hpp @@ -0,0 +1,113 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GFRAME_HPP +#define OPENCV_GAPI_GFRAME_HPP + +#include +#include // std::shared_ptr + +#include +#include // GShape + +#include +#include + +// TODO GAPI_EXPORTS or so +namespace cv +{ +// Forward declaration; GNode and GOrigin are an internal +// (user-inaccessible) classes. +class GNode; +struct GOrigin; + +/** \addtogroup gapi_data_objects + * @{ + */ +/** + * @brief GFrame class represents an image or media frame in the graph. + * + * GFrame doesn't store any data itself, instead it describes a + * functional relationship between operations consuming and producing + * GFrame objects. + * + * GFrame is introduced to handle various media formats (e.g., NV12 or + * I420) under the same type. Various image formats may differ in the + * number of planes (e.g. two for NV12, three for I420) and the pixel + * layout inside. GFrame type allows to handle these media formats in + * the graph uniformly -- the graph structure will not change if the + * media format changes, e.g. a different camera or decoder is used + * with the same graph. G-API provides a number of operations which + * operate directly on GFrame, like `infer<>()` or + * renderFrame(); these operations are expected to handle different + * media formats inside. There is also a number of accessor + * operations like BGR(), Y(), UV() -- these operations provide + * access to frame's data in the familiar cv::GMat form, which can be + * used with the majority of the existing G-API operations. These + * accessor functions may perform color space conversion on the fly if + * the image format of the GFrame they are applied to differs from the + * operation's semantic (e.g. the BGR() accessor is called on an NV12 + * image frame). + * + * GFrame is a virtual counterpart of cv::MediaFrame. + * + * @sa cv::MediaFrame, cv::GFrameDesc, BGR(), Y(), UV(), infer<>(). + */ +class GAPI_EXPORTS_W_SIMPLE GFrame +{ +public: + /** + * @brief Constructs an empty GFrame + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GFrame is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ + GAPI_WRAP GFrame(); // Empty constructor + + /// @private + GFrame(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GOrigin& priv(); // Internal use only + /// @private + const GOrigin& priv() const; // Internal use only + +private: + std::shared_ptr m_priv; +}; +/** @} */ + +enum class MediaFormat: int +{ + BGR = 0, + NV12, + GRAY, +}; + +/** + * \addtogroup gapi_meta_args + * @{ + */ +struct GAPI_EXPORTS GFrameDesc +{ + MediaFormat fmt; + cv::Size size; + + bool operator== (const GFrameDesc &) const; +}; +static inline GFrameDesc empty_gframe_desc() { return GFrameDesc{}; } +/** @} */ + +class MediaFrame; +GAPI_EXPORTS GFrameDesc descr_of(const MediaFrame &frame); + +GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GFrameDesc &desc); + +} // namespace cv + +#endif // OPENCV_GAPI_GFRAME_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gkernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gkernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6ec6bf573d0af5ed275610fdff00bdccca468d43 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gkernel.hpp @@ -0,0 +1,757 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_GKERNEL_HPP +#define OPENCV_GAPI_GKERNEL_HPP + +#include +#include +#include // string +#include // false_type, true_type +#include // map (for GKernelPackage) +#include // tuple + +#include // CompileArgTag +#include // Seq +#include +#include // GArg +#include // GMetaArg +#include // GTypeTraits +#include //suppress_unused_warning +#include + +namespace cv { + +struct GTypeInfo +{ + GShape shape; + cv::detail::OpaqueKind kind; + detail::HostCtor ctor; +}; + +using GShapes = std::vector; +using GKinds = std::vector; +using GCtors = std::vector; +using GTypesInfo = std::vector; + +// GKernel describes kernel API to the system +// FIXME: add attributes of a kernel, (e.g. number and types +// of inputs, etc) +struct GAPI_EXPORTS GKernel +{ + using M = std::function; + + std::string name; // kernel ID, defined by its API (signature) + std::string tag; // some (implementation-specific) tag + M outMeta; // generic adaptor to API::outMeta(...) + GShapes outShapes; // types (shapes) kernel's outputs + GKinds inKinds; // kinds of kernel's inputs (fixme: below) + GCtors outCtors; // captured constructors for template output types + GKinds outKinds; // kinds of kernel's outputs (fixme: below) +}; +// TODO: It's questionable if inKinds should really be here. Instead, +// this information could come from meta. + +// GKernelImpl describes particular kernel implementation to the system +struct GAPI_EXPORTS GKernelImpl +{ + util::any opaque; // backend-specific opaque info + GKernel::M outMeta; // for deserialized graphs, the outMeta is taken here +}; + +template class GKernelTypeM; + +namespace detail +{ + //////////////////////////////////////////////////////////////////////////// + // yield() is used in graph construction time as a generic method to obtain + // lazy "return value" of G-API operations + // + template struct Yield; + template<> struct Yield + { + static inline cv::GMat yield(cv::GCall &call, int i) { return call.yield(i); } + }; + template<> struct Yield + { + static inline cv::GMatP yield(cv::GCall &call, int i) { return call.yieldP(i); } + }; + template<> struct Yield + { + static inline cv::GScalar yield(cv::GCall &call, int i) { return call.yieldScalar(i); } + }; + template struct Yield > + { + static inline cv::GArray yield(cv::GCall &call, int i) { return call.yieldArray(i); } + }; + template struct Yield > + { + static inline cv::GOpaque yield(cv::GCall &call, int i) { return call.yieldOpaque(i); } + }; + template<> struct Yield + { + static inline cv::GFrame yield(cv::GCall &call, int i) { return call.yieldFrame(i); } + }; + + //////////////////////////////////////////////////////////////////////////// + // Helper classes which brings outputMeta() marshalling to kernel + // implementations + // + // 1. MetaType establishes G#Type -> G#Meta mapping between G-API dynamic + // types and its metadata descriptor types. + // This mapping is used to transform types to call outMeta() callback. + template struct MetaType; + template<> struct MetaType { using type = GMatDesc; }; + template<> struct MetaType { using type = GMatDesc; }; + template<> struct MetaType { using type = GFrameDesc; }; + template<> struct MetaType { using type = GScalarDesc; }; + template struct MetaType > { using type = GArrayDesc; }; + template struct MetaType > { using type = GOpaqueDesc; }; + template struct MetaType { using type = T; }; // opaque args passed as-is + // FIXME: Move it to type traits? + + // 2. Hacky test based on MetaType to check if we operate on G-* type or not + template using is_nongapi_type = std::is_same::type>; + + // 3. Two ways to transform input arguments to its meta - for G-* and non-G* types: + template + typename std::enable_if::value, typename MetaType::type> + ::type get_in_meta(const GMetaArgs &in_meta, const GArgs &, int idx) + { + return util::get::type>(in_meta.at(idx)); + } + + template + typename std::enable_if::value, T> + ::type get_in_meta(const GMetaArgs &, const GArgs &in_args, int idx) + { + return in_args.at(idx).template get(); + } + + // 4. The MetaHelper itself: an entity which generates outMeta() call + // based on kernel signature, with arguments properly substituted. + // 4.1 - case for multiple return values + // FIXME: probably can be simplified with std::apply or analogue. + template + struct MetaHelper; + + template + struct MetaHelper, std::tuple > + { + template + static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta, + const GArgs &in_args, + detail::Seq, + detail::Seq) + { + // FIXME: decay? + using R = std::tuple::type...>; + const R r = K::outMeta( get_in_meta(in_meta, in_args, IIs)... ); + return GMetaArgs{ GMetaArg(std::get(r))... }; + } + // FIXME: help users identify how outMeta must look like (via default impl w/static_assert?) + + static GMetaArgs getOutMeta(const GMetaArgs &in_meta, + const GArgs &in_args) + { + return getOutMeta_impl(in_meta, + in_args, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } + }; + + // 4.1 - case for a single return value + // FIXME: How to avoid duplication here? + template + struct MetaHelper, Out > + { + template + static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta, + const GArgs &in_args, + detail::Seq) + { + // FIXME: decay? + using R = typename MetaType::type; + const R r = K::outMeta( get_in_meta(in_meta, in_args, IIs)... ); + return GMetaArgs{ GMetaArg(r) }; + } + // FIXME: help users identify how outMeta must look like (via default impl w/static_assert?) + + static GMetaArgs getOutMeta(const GMetaArgs &in_meta, + const GArgs &in_args) + { + return getOutMeta_impl(in_meta, + in_args, + typename detail::MkSeq::type()); + } + }; + + //////////////////////////////////////////////////////////////////////////// + // Helper class to introduce tags to calls. By default there's no tag + struct NoTag { + static constexpr const char *tag() { return ""; } + }; + +} // namespace detail + +// GKernelType and GKernelTypeM are base classes which implement typed ::on() +// method based on kernel signature. GKernelTypeM stands for multiple-return-value kernels +// +// G_TYPED_KERNEL and G_TYPED_KERNEL_M macros inherit user classes from GKernelType and +// GKernelTypeM respectively. + +template +class GKernelTypeM(Args...)> > + : public detail::MetaHelper, std::tuple> + , public detail::NoTag +{ + template + static std::tuple yield(cv::GCall &call, detail::Seq) + { + return std::make_tuple(detail::Yield::yield(call, IIs)...); + } + +public: + using InArgs = std::tuple; + using OutArgs = std::tuple; + + // TODO: Args&&... here? + static std::tuple on(Args... args) + { + cv::GCall call(GKernel{ K::id() + , K::tag() + , &K::getOutMeta + , {detail::GTypeTraits::shape...} + , {detail::GTypeTraits::op_kind...} + , {detail::GObtainCtor::get()...} + , {detail::GTypeTraits::op_kind...}}); + call.pass(args...); // TODO: std::forward() here? + return yield(call, typename detail::MkSeq::type()); + } +}; + +template class GKernelType; + +template +class GKernelType > + : public detail::MetaHelper, R> + , public detail::NoTag +{ +public: + using InArgs = std::tuple; + using OutArgs = std::tuple; + + static R on(Args... args) + { + cv::GCall call(GKernel{ K::id() + , K::tag() + , &K::getOutMeta + , {detail::GTypeTraits::shape} + , {detail::GTypeTraits::op_kind...} + , {detail::GObtainCtor::get()} + , {detail::GTypeTraits::op_kind}}); + call.pass(args...); + return detail::Yield::yield(call, 0); + } +}; + +namespace detail { +// This tiny class eliminates the semantic difference between +// GKernelType and GKernelTypeM. +template class KernelTypeMedium; + +template +class KernelTypeMedium(Args...)>> : + public cv::GKernelTypeM(Args...)>> {}; + +template +class KernelTypeMedium> : + public cv::GKernelType> {}; +} // namespace detail + +} // namespace cv + + +// FIXME: I don't know a better way so far. Feel free to suggest one +// The problem is that every typed kernel should have ::id() but body +// of the class is defined by user (with outMeta, other stuff) + +//! @cond IGNORED +#define G_ID_HELPER_CLASS(Class) Class##IdHelper + +#define G_ID_HELPER_BODY(Class, Id) \ + struct G_ID_HELPER_CLASS(Class) \ + { \ + static constexpr const char * id() {return Id;} \ + }; \ +//! @endcond + +#define GET_G_TYPED_KERNEL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, NAME, ...) NAME +#define COMBINE_SIGNATURE(...) __VA_ARGS__ +// Ensure correct __VA_ARGS__ expansion on Windows +#define __WRAP_VAARGS(x) x + +/** + * Helper for G_TYPED_KERNEL declares a new G-API Operation. See [Kernel API](@ref gapi_kernel_api) + * for more details. + * + * @param Class type name for this operation. + * @param API an `std::function<>`-like signature for the operation; + * return type is a single value or a tuple of multiple values. + * @param Id string identifier for the operation. Must be unique. + */ +#define G_TYPED_KERNEL_HELPER(Class, API, Id) \ + G_ID_HELPER_BODY(Class, Id) \ + struct Class final: public cv::detail::KernelTypeMedium, \ + public G_ID_HELPER_CLASS(Class) +// {body} is to be defined by user + +#define G_TYPED_KERNEL_HELPER_2(Class, _1, _2, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2), Id) + +#define G_TYPED_KERNEL_HELPER_3(Class, _1, _2, _3, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3), Id) + +#define G_TYPED_KERNEL_HELPER_4(Class, _1, _2, _3, _4, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4), Id) + +#define G_TYPED_KERNEL_HELPER_5(Class, _1, _2, _3, _4, _5, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5), Id) + +#define G_TYPED_KERNEL_HELPER_6(Class, _1, _2, _3, _4, _5, _6, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5, _6), Id) + +#define G_TYPED_KERNEL_HELPER_7(Class, _1, _2, _3, _4, _5, _6, _7, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5, _6, _7), Id) + +#define G_TYPED_KERNEL_HELPER_8(Class, _1, _2, _3, _4, _5, _6, _7, _8, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5, _6, _7, _8), Id) + +#define G_TYPED_KERNEL_HELPER_9(Class, _1, _2, _3, _4, _5, _6, _7, _8, _9, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5, _6, _7, _8, _9), Id) + +#define G_TYPED_KERNEL_HELPER_10(Class, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, Id) \ +G_TYPED_KERNEL_HELPER(Class, COMBINE_SIGNATURE(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10), Id) + +/** + * Declares a new G-API Operation. See [Kernel API](@ref gapi_kernel_api) + * for more details. + * + * @param Class type name for this operation. + */ +#define G_TYPED_KERNEL(Class, ...) __WRAP_VAARGS(GET_G_TYPED_KERNEL(__VA_ARGS__, \ + G_TYPED_KERNEL_HELPER_10, \ + G_TYPED_KERNEL_HELPER_9, \ + G_TYPED_KERNEL_HELPER_8, \ + G_TYPED_KERNEL_HELPER_7, \ + G_TYPED_KERNEL_HELPER_6, \ + G_TYPED_KERNEL_HELPER_5, \ + G_TYPED_KERNEL_HELPER_4, \ + G_TYPED_KERNEL_HELPER_3, \ + G_TYPED_KERNEL_HELPER_2, \ + G_TYPED_KERNEL_HELPER)(Class, __VA_ARGS__)) \ + +/** + * Declares a new G-API Operation. See [Kernel API](@ref gapi_kernel_api) for more details. + * + * @deprecated This macro is deprecated in favor of `G_TYPED_KERNEL` that is used for declaring any + * G-API Operation. + * + * @param Class type name for this operation. + */ +#define G_TYPED_KERNEL_M G_TYPED_KERNEL + +#define G_API_OP G_TYPED_KERNEL +#define G_API_OP_M G_API_OP + +namespace cv +{ +namespace gapi +{ + // Prework: model "Device" API before it gets to G-API headers. + // FIXME: Don't mix with internal Backends class! + /// @private + class GAPI_EXPORTS GBackend + { + public: + class Priv; + + // TODO: make it template (call `new` within??) + GBackend(); + explicit GBackend(std::shared_ptr &&p); + + Priv& priv(); + const Priv& priv() const; + std::size_t hash() const; + + bool operator== (const GBackend &rhs) const; + + private: + std::shared_ptr m_priv; + }; + + inline bool operator != (const GBackend &lhs, const GBackend &rhs) + { + return !(lhs == rhs); + } +} // namespace gapi +} // namespace cv + +namespace std +{ + template<> struct hash + { + std::size_t operator() (const cv::gapi::GBackend &b) const + { + return b.hash(); + } + }; +} // namespace std + +namespace cv { + class GAPI_EXPORTS_W_SIMPLE GKernelPackage; + +namespace gapi { + GAPI_EXPORTS_W cv::GKernelPackage combine(const cv::GKernelPackage &lhs, + const cv::GKernelPackage &rhs); + + /// @private + class GFunctor + { + public: + virtual cv::GKernelImpl impl() const = 0; + virtual cv::gapi::GBackend backend() const = 0; + const char* id() const { return m_id; } + + virtual ~GFunctor() = default; + protected: + GFunctor(const char* id) : m_id(id) { } + private: + const char* m_id; + }; +} // namespace gapi + + /** \addtogroup gapi_compile_args + * @{ + */ + + // FIXME: Hide implementation + /** + * @brief A container class for heterogeneous kernel + * implementation collections and graph transformations. + * + * GKernelPackage is a special container class which stores kernel + * _implementations_ and graph _transformations_. Objects of this class + * are created and passed to cv::GComputation::compile() to specify + * which kernels to use and which transformations to apply in the + * compiled graph. GKernelPackage may contain kernels of + * different backends, e.g. be heterogeneous. + * + * The most easy way to create a kernel package is to use function + * cv::gapi::kernels(). This template functions takes kernel + * implementations in form of type list (variadic template) and + * generates a kernel package atop of that. + * + * Kernel packages can be also generated programmatically, starting + * with an empty package (created with the default constructor) + * and then by populating it with kernels via call to + * GKernelPackage::include(). Note this method is also a template + * one since G-API kernel and transformation implementations are _types_, + * not objects. + * + * Finally, two kernel packages can be combined into a new one + * with function cv::gapi::combine(). + */ + class GAPI_EXPORTS_W_SIMPLE GKernelPackage + { + + /// @private + using M = std::unordered_map>; + + /// @private + M m_id_kernels; + + /// @private + std::vector m_transformations; + + protected: + /// @private + // Remove ALL implementations of the given API (identified by ID) + void removeAPI(const std::string &id); + + /// @private + // Partial include() specialization for kernels + template + typename std::enable_if<(std::is_base_of::value), void>::type + includeHelper() + { + auto backend = KImpl::backend(); + auto kernel_id = KImpl::API::id(); + auto kernel_impl = GKernelImpl{KImpl::kernel(), &KImpl::API::getOutMeta}; + removeAPI(kernel_id); + + m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl); + } + + /// @private + // Partial include() specialization for transformations + template + typename std::enable_if<(std::is_base_of::value), void>::type + includeHelper() + { + m_transformations.emplace_back(TImpl::transformation()); + } + + public: + void include(const cv::gapi::GFunctor& functor); + + /** + * @brief Returns total number of kernels + * in the package (across all backends included) + * + * @return a number of kernels in the package + */ + GAPI_WRAP std::size_t size() const; + + /** + * @brief Returns vector of transformations included in the package + * + * @return vector of transformations included in the package + */ + const std::vector& get_transformations() const; + + /** + * @brief Returns vector of kernel ids included in the package + * + * @return vector of kernel ids included in the package + */ + std::vector get_kernel_ids() const; + + /** + * @brief Test if a particular kernel _implementation_ KImpl is + * included in this kernel package. + * + * @sa includesAPI() + * + * @note cannot be applied to transformations + * + * @return true if there is such kernel, false otherwise. + */ + template + bool includes() const + { + static_assert(std::is_base_of::value, + "includes() can be applied to kernels only"); + + auto kernel_it = m_id_kernels.find(KImpl::API::id()); + return kernel_it != m_id_kernels.end() && + kernel_it->second.first == KImpl::backend(); + } + + /** + * @brief Remove all kernels associated with the given backend + * from the package. + * + * Does nothing if there's no kernels of this backend in the package. + * + * @param backend backend which kernels to remove + */ + void remove(const cv::gapi::GBackend& backend); + + /** + * @brief Remove all kernels implementing the given API from + * the package. + * + * Does nothing if there's no kernels implementing the given interface. + */ + template + void remove() + { + removeAPI(KAPI::id()); + } + + // FIXME: Rename to includes() and distinguish API/impl case by + // statically? + /** + * Check if package contains ANY implementation of a kernel API + * by API type. + */ + template + bool includesAPI() const + { + return includesAPI(KAPI::id()); + } + + /// @private + bool includesAPI(const std::string &id) const; + + // FIXME: The below comment is wrong, and who needs this function? + /** + * @brief Find a kernel (by its API) + * + * Returns implementation corresponding id. + * Throws if nothing found. + * + * @return Backend which hosts matching kernel implementation. + * + */ + template + cv::gapi::GBackend lookup() const + { + return lookup(KAPI::id()).first; + } + + /// @private + std::pair + lookup(const std::string &id) const; + + // FIXME: No overwrites allowed? + /** + * @brief Put a new kernel implementation or a new transformation + * KImpl into the package. + */ + template + void include() + { + includeHelper(); + } + + /** + * @brief Adds a new kernel based on it's backend and id into the kernel package + * + * @param backend backend associated with the kernel + * @param kernel_id a name/id of the kernel + */ + void include(const cv::gapi::GBackend& backend, const std::string& kernel_id); + + /** + * @brief Lists all backends which are included into package + * + * @return vector of backends + */ + std::vector backends() const; + + // TODO: Doxygen bug -- it wants me to place this comment + // here, not below. + /** + * @brief Create a new package based on `lhs` and `rhs`. + * + * @param lhs "Left-hand-side" package in the process + * @param rhs "Right-hand-side" package in the process + * @return a new kernel package. + */ + friend GAPI_EXPORTS GKernelPackage cv::gapi::combine(const GKernelPackage &lhs, + const GKernelPackage &rhs); + }; + /** @} */ + +namespace gapi { + using GKernelPackage = cv::GKernelPackage; // Keep backward compatibility + + /** \addtogroup gapi_compile_args + * @{ + */ + + /** + * @brief Create a kernel package object containing kernels + * and transformations specified in variadic template argument. + * + * In G-API, kernel implementations and transformations are _types_. + * Every backend has its own kernel API (like GAPI_OCV_KERNEL() and + * GAPI_FLUID_KERNEL()) but all of that APIs define a new type for + * each kernel implementation. + * + * Use this function to pass kernel implementations (defined in + * either way) and transformations to the system. Example: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp kernels_snippet + * + * Note that kernels() itself is a function returning object, not + * a type, so having `()` at the end is important -- it must be a + * function call. + */ + template GKernelPackage kernels() + { + // FIXME: currently there is no check that transformations' signatures are unique + // and won't be any intersection in graph compilation stage + static_assert(cv::detail::all_unique::value, "Kernels API must be unique"); + + GKernelPackage pkg; + + // For those who wonder - below is a trick to call a number of + // methods based on parameter pack (zeroes just help hiding these + // calls into a sequence which helps to expand this parameter pack). + // Just note that `f(),a` always equals to `a` (with f() called!) + // and parentheses are used to hide function call in the expanded sequence. + // Leading 0 helps to handle case when KK is an empty list (kernels<>()). + int unused[] = { 0, (pkg.include(), 0)... }; + cv::util::suppress_unused_warning(unused); + return pkg; + } + + template + GKernelPackage kernels(FF&... functors) + { + GKernelPackage pkg; + int unused[] = { 0, (pkg.include(functors), 0)... }; + cv::util::suppress_unused_warning(unused); + return pkg; + } + + /** @} */ + + /** + * @brief Combines multiple G-API kernel packages into one + * + * @overload + * + * This function successively combines the passed kernel packages using a right fold. + * Calling `combine(a, b, c)` is equal to `combine(a, combine(b, c))`. + * + * @return The resulting kernel package + */ + template + cv::GKernelPackage combine(const cv::GKernelPackage &a, const cv::GKernelPackage &b, Ps&&... rest) + { + return combine(a, combine(b, rest...)); + } + // NB(DM): Variadic-arg version in Python may require the same + // approach as used in GComputation::compile/apply. + + /** \addtogroup gapi_compile_args + * @{ + */ + /** + * @brief cv::gapi::use_only() is a special combinator which hints G-API to use only + * kernels specified in cv::GComputation::compile() (and not to extend kernels available by + * default with that package). + */ + struct GAPI_EXPORTS use_only + { + GKernelPackage pkg; + }; + /** @} */ + +} // namespace gapi + +namespace detail +{ + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.kernel_package"; } + }; + + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.use_only"; } + }; +} // namespace detail + +} // namespace cv + +#endif // OPENCV_GAPI_GKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmat.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6d6f74ff7f4df9d77ef85620dbeb23c3aa4db3f9 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmat.hpp @@ -0,0 +1,292 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GMAT_HPP +#define OPENCV_GAPI_GMAT_HPP + +#include +#include // std::shared_ptr + +#include +#include // GShape + +#include + +// TODO GAPI_EXPORTS or so +namespace cv +{ +// Forward declaration; GNode and GOrigin are an internal +// (user-inaccessible) classes. +class GNode; +struct GOrigin; + +/** \addtogroup gapi_data_objects + * @{ + * + * @brief G-API data objects used to build G-API expressions. + * + * These objects do not own any particular data (except compile-time + * associated values like with cv::GScalar or `cv::GArray`) and are + * used only to construct graphs. + * + * Every graph in G-API starts and ends with data objects. + * + * Once constructed and compiled, G-API operates with regular host-side + * data instead. Refer to the below table to find the mapping between + * G-API and regular data types when passing input and output data + * structures to G-API: + * + * G-API data type | I/O data type + * ------------------ | ------------- + * cv::GMat | cv::Mat, cv::UMat, cv::RMat + * cv::GScalar | cv::Scalar + * `cv::GArray` | std::vector + * `cv::GOpaque` | T + * cv::GFrame | cv::MediaFrame + */ + +/** + * @brief GMat class represents image or tensor data in the + * graph. + * + * GMat doesn't store any data itself, instead it describes a + * functional relationship between operations consuming and producing + * GMat objects. + * + * GMat is a virtual counterpart of Mat and UMat, but it + * doesn't mean G-API use Mat or UMat objects internally to represent + * GMat objects -- the internal data representation may be + * backend-specific or optimized out at all. + * + * @sa Mat, GMatDesc + */ +class GAPI_EXPORTS_W_SIMPLE GMat +{ +public: + /** + * @brief Constructs an empty GMat + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GMat is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ + GAPI_WRAP GMat(); // Empty constructor + + /** + * @brief Constructs a value-initialized GMat + * + * GMat may be associated with a buffer at graph construction time. + * It is useful when some operation has a Mat input which doesn't + * change during the program execution, and is set only once. + * In this case, there's no need to declare such GMat as graph input. + * + * @param m a cv::Mat buffer to associate with this GMat object. + */ + GAPI_WRAP explicit GMat(cv::Mat m); // Value-initialization constructor + + /// @private + GMat(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GOrigin& priv(); // Internal use only + /// @private + const GOrigin& priv() const; // Internal use only + +private: + std::shared_ptr m_priv; +}; + +class GAPI_EXPORTS GMatP : public GMat +{ +public: + using GMat::GMat; +}; + +class RMat; + +/** @} */ + +/** + * \addtogroup gapi_meta_args + * @{ + */ +struct GAPI_EXPORTS_W_SIMPLE GMatDesc +{ + // FIXME: Default initializers in C++14 + GAPI_PROP int depth; + GAPI_PROP int chan; + GAPI_PROP cv::Size size; // NB.: no multi-dimensional cases covered yet + GAPI_PROP bool planar; + GAPI_PROP std::vector dims; // FIXME: Maybe it's real questionable to have it here + + GAPI_WRAP GMatDesc(int d, int c, cv::Size s, bool p = false) + : depth(d), chan(c), size(s), planar(p) {} + + GAPI_WRAP GMatDesc(int d, const std::vector &dd) + : depth(d), chan(-1), size{-1,-1}, planar(false), dims(dd) {} + + GAPI_WRAP GMatDesc(int d, std::vector &&dd) + : depth(d), chan(-1), size{-1,-1}, planar(false), dims(std::move(dd)) {} + + GAPI_WRAP GMatDesc() : GMatDesc(-1, -1, {-1,-1}) {} + + inline bool operator== (const GMatDesc &rhs) const + { + return depth == rhs.depth + && chan == rhs.chan + && size == rhs.size + && planar == rhs.planar + && dims == rhs.dims; + } + + inline bool operator!= (const GMatDesc &rhs) const + { + return !(*this == rhs); + } + + bool isND() const { return !dims.empty(); } + + // Checks if the passed mat can be described by this descriptor + // (it handles the case when + // 1-channel mat can be reinterpreted as is (1-channel mat) + // and as a 3-channel planar mat with height divided by 3) + bool canDescribe(const cv::Mat& mat) const; + + bool canDescribe(const cv::RMat& mat) const; + + // Meta combinator: return a new GMatDesc which differs in size by delta + // (all other fields are taken unchanged from this GMatDesc) + // FIXME: a better name? + GAPI_WRAP GMatDesc withSizeDelta(cv::Size delta) const + { + GMatDesc desc(*this); + desc.size += delta; + return desc; + } + // Meta combinator: return a new GMatDesc which differs in size by delta + // (all other fields are taken unchanged from this GMatDesc) + // + // This is an overload. + GAPI_WRAP GMatDesc withSizeDelta(int dx, int dy) const + { + return withSizeDelta(cv::Size{dx,dy}); + } + + GAPI_WRAP GMatDesc withSize(cv::Size sz) const + { + GMatDesc desc(*this); + desc.size = sz; + return desc; + } + + // Meta combinator: return a new GMatDesc with specified data depth. + // (all other fields are taken unchanged from this GMatDesc) + GAPI_WRAP GMatDesc withDepth(int ddepth) const + { + GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1); + GMatDesc desc(*this); + if (ddepth != -1) desc.depth = ddepth; + return desc; + } + + // Meta combinator: return a new GMatDesc with specified data depth + // and number of channels. + // (all other fields are taken unchanged from this GMatDesc) + GAPI_WRAP GMatDesc withType(int ddepth, int dchan) const + { + GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1); + GMatDesc desc = withDepth(ddepth); + desc.chan = dchan; + return desc; + } + + // Meta combinator: return a new GMatDesc with planar flag set + // (no size changes are performed, only channel interpretation is changed + // (interleaved -> planar) + GAPI_WRAP GMatDesc asPlanar() const + { + GAPI_Assert(planar == false); + GMatDesc desc(*this); + desc.planar = true; + return desc; + } + + // Meta combinator: return a new GMatDesc + // reinterpreting 1-channel input as planar image + // (size height is divided by plane number) + GAPI_WRAP GMatDesc asPlanar(int planes) const + { + GAPI_Assert(planar == false); + GAPI_Assert(chan == 1); + GAPI_Assert(planes > 1); + GAPI_Assert(size.height % planes == 0); + GMatDesc desc(*this); + desc.size.height /= planes; + desc.chan = planes; + return desc.asPlanar(); + } + + // Meta combinator: return a new GMatDesc with planar flag set to false + // (no size changes are performed, only channel interpretation is changed + // (planar -> interleaved) + GAPI_WRAP GMatDesc asInterleaved() const + { + GAPI_Assert(planar == true); + GMatDesc desc(*this); + desc.planar = false; + return desc; + } +}; + +static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; } + +namespace gapi { namespace detail { +/** Checks GMatDesc fields if the passed matrix is a set of n-dimentional points. +@param in GMatDesc to check. +@param n expected dimensionality. +@return the amount of points. In case input matrix can't be described as vector of points +of expected dimensionality, returns -1. + */ +int checkVector(const GMatDesc& in, const size_t n); + +/** @overload + +Checks GMatDesc fields if the passed matrix can be described as a set of points of any +dimensionality. + +@return array of two elements in form of std::vector: the amount of points +and their calculated dimensionality. In case input matrix can't be described as vector of points, +returns {-1, -1}. + */ +std::vector checkVector(const GMatDesc& in); +}} // namespace gapi::detail + +#if !defined(GAPI_STANDALONE) +GAPI_EXPORTS GMatDesc descr_of(const cv::UMat &mat); +#endif // !defined(GAPI_STANDALONE) + +//Fwd declarations +namespace gapi { namespace own { + class Mat; + GAPI_EXPORTS GMatDesc descr_of(const Mat &mat); +}}//gapi::own + +GAPI_EXPORTS GMatDesc descr_of(const RMat &mat); + +#if !defined(GAPI_STANDALONE) +GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat); +#else +using gapi::own::descr_of; +#endif + +/** @} */ + +GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc); + +} // namespace cv + +#endif // OPENCV_GAPI_GMAT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmetaarg.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmetaarg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f21182c19f461a77e167068f8a74113bfdb2eaf8 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gmetaarg.hpp @@ -0,0 +1,80 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GMETAARG_HPP +#define OPENCV_GAPI_GMETAARG_HPP + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace cv +{ +// FIXME: Rename to GMeta? +// FIXME: user shouldn't deal with it - put to detail? +// GMetaArg is an union type over descriptions of G-types which can serve as +// GComputation's in/output slots. +// +// GMetaArg objects are passed as arguments to GComputation::compile() +// to specify which data a compiled computation should be specialized on. +// For manual compile(), user must supply this metadata, in case of apply() +// this metadata is taken from arguments computation should operate on. +// +// The first type (monostate) is equal to "uninitialized"/"unresolved" meta. +using GMetaArg = util::variant + < util::monostate + , GMatDesc + , GScalarDesc + , GArrayDesc + , GOpaqueDesc + , GFrameDesc + >; +GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const GMetaArg &); + +using GMetaArgs = std::vector; + +namespace detail +{ + // These traits are used by GComputation::compile() + + // FIXME: is_constructible doesn't work as variant doesn't do any SFINAE + // in its current template constructor + + template struct is_meta_descr : std::false_type {}; + template<> struct is_meta_descr : std::true_type {}; + template<> struct is_meta_descr : std::true_type {}; + template<> struct is_meta_descr : std::true_type {}; + template<> struct is_meta_descr : std::true_type {}; + + template + using are_meta_descrs = all_satisfy; + + template + using are_meta_descrs_but_last = all_satisfy::type>; + +} // namespace detail + +// Note: descr_of(std::vector<..>) returns a GArrayDesc, while +// descrs_of(std::vector<..>) returns an array of Meta args! +class UMat; +GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector &vec); +GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector &vec); +namespace gapi { namespace own { + GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector &vec); +}} // namespace gapi::own + +} // namespace cv + +#endif // OPENCV_GAPI_GMETAARG_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gopaque.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gopaque.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a3f98a9867e8993e32bc12066af3e8417a63825e --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gopaque.hpp @@ -0,0 +1,369 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GOPAQUE_HPP +#define OPENCV_GAPI_GOPAQUE_HPP + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include // OpaqueKind +#include // TypeHintBase + +namespace cv +{ +// Forward declaration; GNode and GOrigin are an internal +// (user-inaccessible) classes. +class GNode; +struct GOrigin; +template class GOpaque; + +/** + * \addtogroup gapi_meta_args + * @{ + */ +struct GAPI_EXPORTS_W_SIMPLE GOpaqueDesc +{ + // FIXME: Body + // FIXME: Also implement proper operator== then + bool operator== (const GOpaqueDesc&) const { return true; } +}; +template GOpaqueDesc descr_of(const U &) { return {};} +GAPI_EXPORTS_W inline GOpaqueDesc empty_gopaque_desc() {return {}; } +/** @} */ + +std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &desc); + +namespace detail +{ + // ConstructOpaque is a callback which stores information about T and is used by + // G-API runtime to construct an object in host memory (T remains opaque for G-API). + // ConstructOpaque is carried into G-API internals by GOpaqueU. + // Currently it is suitable for Host (CPU) plugins only, real offload may require + // more information for manual memory allocation on-device. + class OpaqueRef; + using ConstructOpaque = std::function; + + // FIXME: garray.hpp already contains hint classes (for actual T type verification), + // need to think where it can be moved (currently opaque uses it from garray) + + // This class strips type information from GOpaque and makes it usable + // in the G-API graph compiler (expression unrolling, graph generation, etc). + // Part of GProtoArg. + class GAPI_EXPORTS GOpaqueU + { + public: + GOpaqueU(const GNode &n, std::size_t out); // Operation result constructor + + template + bool holds() const; // Check if was created from GOpaque + + GOrigin& priv(); // Internal use only + const GOrigin& priv() const; // Internal use only + + protected: + GOpaqueU(); // Default constructor + template friend class cv::GOpaque; // (available for GOpaque only) + + void setConstructFcn(ConstructOpaque &&cv); // Store T-aware constructor + + template + void specifyType(); // Store type of initial GOpaque + + template + void storeKind(); + + void setKind(cv::detail::OpaqueKind); + + std::shared_ptr m_priv; + std::shared_ptr m_hint; + }; + + template + bool GOpaqueU::holds() const{ + GAPI_Assert(m_hint != nullptr); + using U = util::decay_t; + return dynamic_cast*>(m_hint.get()) != nullptr; + } + + template + void GOpaqueU::specifyType(){ + m_hint.reset(new TypeHint>); + } + + template + void GOpaqueU::storeKind(){ + // FIXME: Add assert here on cv::Mat and cv::Scalar? + setKind(cv::detail::GOpaqueTraits::kind); + } + + // This class represents a typed object reference. + // Depending on origins, this reference may be either "just a" reference to + // an object created externally, OR actually own the underlying object + // (be value holder). + class BasicOpaqueRef + { + public: + cv::GOpaqueDesc m_desc; + virtual ~BasicOpaqueRef() {} + + virtual void mov(BasicOpaqueRef &ref) = 0; + virtual const void* ptr() const = 0; + virtual void set(const cv::util::any &a) = 0; + }; + + template class OpaqueRefT final: public BasicOpaqueRef + { + using empty_t = util::monostate; + using ro_ext_t = const T *; + using rw_ext_t = T *; + using rw_own_t = T ; + util::variant m_ref; + + inline bool isEmpty() const { return util::holds_alternative(m_ref); } + inline bool isROExt() const { return util::holds_alternative(m_ref); } + inline bool isRWExt() const { return util::holds_alternative(m_ref); } + inline bool isRWOwn() const { return util::holds_alternative(m_ref); } + + void init(const T* obj = nullptr) + { + if (obj) m_desc = cv::descr_of(*obj); + } + + public: + OpaqueRefT() { init(); } + virtual ~OpaqueRefT() {} + + explicit OpaqueRefT(const T& obj) : m_ref(&obj) { init(&obj); } + explicit OpaqueRefT( T& obj) : m_ref(&obj) { init(&obj); } + explicit OpaqueRefT( T&& obj) : m_ref(std::move(obj)) { init(&obj); } + + // Reset a OpaqueRefT. Called only for objects instantiated + // internally in G-API (e.g. temporary GOpaque's within a + // computation). Reset here means both initialization + // (creating an object) and reset (discarding its existing + // content before the next execution). Must never be called + // for external OpaqueRefTs. + void reset() + { + if (isEmpty()) + { + T empty_obj{}; + m_desc = cv::descr_of(empty_obj); + m_ref = std::move(empty_obj); + GAPI_Assert(isRWOwn()); + } + else if (isRWOwn()) + { + util::get(m_ref) = {}; + } + else GAPI_Error("InternalError"); // shouldn't be called in *EXT modes + } + + // Obtain a WRITE reference to underlying object + // Used by CPU kernel API wrappers when a kernel execution frame + // is created + T& wref() + { + GAPI_Assert(isRWExt() || isRWOwn()); + if (isRWExt()) return *util::get(m_ref); + if (isRWOwn()) return util::get(m_ref); + util::throw_error(std::logic_error("Impossible happened")); + } + + // Obtain a READ reference to underlying object + // Used by CPU kernel API wrappers when a kernel execution frame + // is created + const T& rref() const + { + // ANY object can be accessed for reading, even if it declared for + // output. Example -- a GComputation from [in] to [out1,out2] + // where [out2] is a result of operation applied to [out1]: + // + // GComputation boundary + // . . . . . . . + // . . + // [in] ----> foo() ----> [out1] + // . . : + // . . . .:. . . + // . V . + // . bar() ---> [out2] + // . . . . . . . . . . . . + // + if (isROExt()) return *util::get(m_ref); + if (isRWExt()) return *util::get(m_ref); + if (isRWOwn()) return util::get(m_ref); + util::throw_error(std::logic_error("Impossible happened")); + } + + virtual void mov(BasicOpaqueRef &v) override { + OpaqueRefT *tv = dynamic_cast*>(&v); + GAPI_Assert(tv != nullptr); + wref() = std::move(tv->wref()); + } + + virtual const void* ptr() const override { return &rref(); } + + virtual void set(const cv::util::any &a) override { + wref() = util::any_cast(a); + } + }; + + // This class strips type information from OpaqueRefT<> and makes it usable + // in the G-API executables (carrying run-time data/information to kernels). + // Part of GRunArg. + // Its methods are typed proxies to OpaqueRefT. + // OpaqueRef maintains "reference" semantics so two copies of OpaqueRef refer + // to the same underlying object. + class OpaqueRef + { + std::shared_ptr m_ref; + cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN; + + template inline void check() const + { + GAPI_DbgAssert(dynamic_cast*>(m_ref.get()) != nullptr); + } + + public: + OpaqueRef() = default; + + template< + typename T, + typename = util::are_different_t + > + // FIXME: probably won't work with const object + explicit OpaqueRef(T&& obj) : + m_ref(new OpaqueRefT>(std::forward(obj))), + m_kind(GOpaqueTraits>::kind) {} + + cv::detail::OpaqueKind getKind() const + { + return m_kind; + } + + template void reset() + { + if (!m_ref) m_ref.reset(new OpaqueRefT()); + check(); + storeKind(); + static_cast&>(*m_ref).reset(); + } + + template + void storeKind() + { + m_kind = cv::detail::GOpaqueTraits::kind; + } + + template T& wref() + { + check(); + return static_cast&>(*m_ref).wref(); + } + + template const T& rref() const + { + check(); + return static_cast&>(*m_ref).rref(); + } + + void mov(OpaqueRef &v) + { + m_ref->mov(*v.m_ref); + } + + cv::GOpaqueDesc descr_of() const + { + return m_ref->m_desc; + } + + // May be used to uniquely identify this object internally + const void *ptr() const { return m_ref->ptr(); } + + // Introduced for in-graph meta handling + OpaqueRef& operator= (const cv::util::any &a) + { + m_ref->set(a); + return *this; + } + }; +} // namespace detail + +/** \addtogroup gapi_data_objects + * @{ + */ +/** + * @brief `cv::GOpaque` template class represents an object of + * class `T` in the graph. + * + * `cv::GOpaque` describes a functional relationship between operations + * consuming and producing object of class `T`. `cv::GOpaque` is + * designed to extend G-API with user-defined data types, which are + * often required with user-defined operations. G-API can't apply any + * optimizations to user-defined types since these types are opaque to + * the framework. However, there is a number of G-API operations + * declared with `cv::GOpaque` as a return type, + * e.g. cv::gapi::streaming::timestamp() or cv::gapi::streaming::size(). + * + * @sa `cv::GArray` + */ +template class GOpaque +{ +public: + // Host type (or Flat type) - the type this GOpaque is actually + // specified to. + /// @private + using HT = typename detail::flatten_g>::type; + + /** + * @brief Constructs an empty `cv::GOpaque` + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty `cv::GOpaque` is assigned to a result + * of some operation, it obtains a functional link to this + * operation (and is not empty anymore). + */ + GOpaque() { putDetails(); } // Empty constructor + + /// @private + explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor + : m_ref(ref) { putDetails(); } // (used by GCall, not for users) + + /// @private + detail::GOpaqueU strip() const { + return m_ref; + } + /// @private + static void Ctor(detail::OpaqueRef& ref) { + ref.reset(); + } +private: + void putDetails() { + m_ref.setConstructFcn(&Ctor); + m_ref.specifyType(); + m_ref.storeKind(); + } + + detail::GOpaqueU m_ref; +}; + +/** @} */ + +} // namespace cv + +#endif // OPENCV_GAPI_GOPAQUE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gproto.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gproto.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a2b5d83bc1e8d3861506a598a5fce6a0036a9f88 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gproto.hpp @@ -0,0 +1,159 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GPROTO_HPP +#define OPENCV_GAPI_GPROTO_HPP + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace cv { + +// FIXME: user shouldn't deal with it - put to detail? +// GProtoArg is an union type over G-types which can serve as +// GComputation's in/output slots. In other words, GProtoArg +// wraps any type which can serve as G-API exchange type. +// +// In Runtime, GProtoArgs are substituted with appropriate GRunArgs. +// +// GProtoArg objects are constructed in-place when user describes +// (captures) computations, user doesn't interact with these types +// directly. +using GProtoArg = util::variant + < GMat + , GMatP + , GFrame + , GScalar + , detail::GArrayU // instead of GArray + , detail::GOpaqueU // instead of GOpaque + >; + +using GProtoArgs = std::vector; + +namespace detail +{ +template inline GProtoArgs packArgs(Ts... args) +{ + return GProtoArgs{ GProtoArg(wrap_gapi_helper::wrap(args))... }; +} + +} + +template +struct GIOProtoArgs +{ +public: + // NB: Used by python wrapper + GIOProtoArgs() = default; + explicit GIOProtoArgs(const GProtoArgs& args) : m_args(args) {} + explicit GIOProtoArgs(GProtoArgs &&args) : m_args(std::move(args)) {} + + GProtoArgs m_args; + + // TODO: Think about the addition operator + /** + * @brief This operator allows to complement the proto vectors at runtime. + * + * It's an ordinary overload of addition assignment operator. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GIOProtoArgs usage + * + */ + template + friend GIOProtoArgs& operator += (GIOProtoArgs &lhs, const GIOProtoArgs &rhs); +}; + +template +cv::GIOProtoArgs& operator += (cv::GIOProtoArgs &lhs, const cv::GIOProtoArgs &rhs) +{ + lhs.m_args.reserve(lhs.m_args.size() + rhs.m_args.size()); + lhs.m_args.insert(lhs.m_args.end(), rhs.m_args.begin(), rhs.m_args.end()); + return lhs; +} + +struct In_Tag{}; +struct Out_Tag{}; + +using GProtoInputArgs = GIOProtoArgs; +using GProtoOutputArgs = GIOProtoArgs; + +// Perfect forwarding +template inline GProtoInputArgs GIn(Ts&&... ts) +{ + return GProtoInputArgs(detail::packArgs(std::forward(ts)...)); +} + +template inline GProtoOutputArgs GOut(Ts&&... ts) +{ + return GProtoOutputArgs(detail::packArgs(std::forward(ts)...)); +} + +namespace detail +{ + // Extract elements form tuple + // FIXME: Someday utilize a generic tuple_to_vec<> routine + template + static GProtoOutputArgs getGOut_impl(const std::tuple& ts, detail::Seq) + { + return GProtoOutputArgs{ detail::packArgs(std::get(ts)...)}; + } +} + +template inline GProtoOutputArgs GOut(const std::tuple& ts) +{ + // TODO: think of std::forward(ts) + return detail::getGOut_impl(ts, typename detail::MkSeq::type()); +} + +// Takes rvalue as input arg +template inline GProtoOutputArgs GOut(std::tuple&& ts) +{ + // TODO: think of std::forward(ts) + return detail::getGOut_impl(ts, typename detail::MkSeq::type()); +} + +// Extract run-time arguments from node origin +// Can be used to extract constant values associated with G-objects +// (like GScalar) at graph construction time +GRunArg value_of(const GOrigin &origin); + +// Transform run-time computation arguments into a collection of metadata +// extracted from that arguments +GMetaArg GAPI_EXPORTS descr_of(const GRunArg &arg ); +GMetaArgs GAPI_EXPORTS descr_of(const GRunArgs &args); + +// Transform run-time operation result argument into metadata extracted from that argument +// Used to compare the metadata, which generated at compile time with the metadata result operation in run time +GMetaArg GAPI_EXPORTS descr_of(const GRunArgP& argp); + +// Checks if run-time computation argument can be described by metadata +bool GAPI_EXPORTS can_describe(const GMetaArg& meta, const GRunArg& arg); +bool GAPI_EXPORTS can_describe(const GMetaArgs& metas, const GRunArgs& args); + +// Checks if run-time computation result argument can be described by metadata. +// Used to check if the metadata generated at compile time +// coincides with output arguments passed to computation in cpu and ocl backends +bool GAPI_EXPORTS can_describe(const GMetaArg& meta, const GRunArgP& argp); + +// Validates input arguments +void GAPI_EXPORTS validate_input_arg(const GRunArg& arg); +void GAPI_EXPORTS validate_input_args(const GRunArgs& args); + +} // namespace cv + +#endif // OPENCV_GAPI_GPROTO_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a7ee59577ce41ca84cc7f36a3752890534303e23 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/core.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GPU_CORE_API_HPP +#define OPENCV_GAPI_GPU_CORE_API_HPP +/** @file +* @deprecated Use instead. +*/ + +#include + +namespace cv { +namespace gapi { +namespace core { +namespace gpu { + using namespace ocl; +} // namespace gpu +} // namespace core +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_GPU_CORE_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/ggpukernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/ggpukernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b52c21de6bf75876457a426afe21bde7e20fdc45 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/ggpukernel.hpp @@ -0,0 +1,18 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GGPUKERNEL_HPP +#define OPENCV_GAPI_GGPUKERNEL_HPP +/** @file +* @deprecated Use instead. +*/ + +#include +#define GAPI_GPU_KERNEL GAPI_OCL_KERNEL + + +#endif // OPENCV_GAPI_GGPUKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/imgproc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0df7ae3315ef17fbd865187e65a390a5243ae16 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gpu/imgproc.hpp @@ -0,0 +1,28 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GPU_IMGPROC_API_HPP +#define OPENCV_GAPI_GPU_IMGPROC_API_HPP +/** @file +* @deprecated Use instead. +*/ + +#include + + +namespace cv { +namespace gapi { +namespace imgproc { +namespace gpu { + using namespace ocl; +} // namespace gpu +} // namespace imgproc +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_GPU_IMGPROC_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gscalar.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gscalar.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de0dfe1383c76b6080eb83595585f87bb1dbf629 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gscalar.hpp @@ -0,0 +1,140 @@ +// This file is part of OpenCV project. + +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GSCALAR_HPP +#define OPENCV_GAPI_GSCALAR_HPP + +#include + +#include +#include // GShape +#include + +namespace cv +{ +// Forward declaration; GNode and GOrigin are an internal +// (user-inaccessible) classes. +class GNode; +struct GOrigin; + +/** \addtogroup gapi_data_objects + * @{ + */ +/** + * @brief GScalar class represents cv::Scalar data in the graph. + * + * GScalar may be associated with a cv::Scalar value, which becomes + * its constant value bound in graph compile time. cv::GScalar describes a + * functional relationship between operations consuming and producing + * GScalar objects. + * + * GScalar is a virtual counterpart of cv::Scalar, which is usually used + * to represent the GScalar data in G-API during the execution. + * + * @sa Scalar + */ +class GAPI_EXPORTS_W_SIMPLE GScalar +{ +public: + /** + * @brief Constructs an empty GScalar + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GScalar is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ + GAPI_WRAP GScalar(); + + /** + * @brief Constructs a value-initialized GScalar + * + * GScalars may have their values be associated at graph + * construction time. It is useful when some operation has a + * GScalar input which doesn't change during the program + * execution, and is set only once. In this case, there is no need + * to declare such GScalar as a graph input. + * + * @note The value of GScalar may be overwritten by assigning some + * other GScalar to the object using `operator=` -- on the + * assignment, the old GScalar value is discarded. + * + * @param s a cv::Scalar value to associate with this GScalar object. + */ + GAPI_WRAP + explicit GScalar(const cv::Scalar& s); + + /** + * @overload + * @brief Constructs a value-initialized GScalar + * + * @param s a cv::Scalar value to associate with this GScalar object. + */ + explicit GScalar(cv::Scalar&& s); // Constant value move-constructor from cv::Scalar + + /** + * @overload + * @brief Constructs a value-initialized GScalar + * + * @param v0 A `double` value to associate with this GScalar. Note + * that only the first component of a four-component cv::Scalar is + * set to this value, with others remain zeros. + * + * This constructor overload is not marked `explicit` and can be + * used in G-API expression code like this: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp gscalar_implicit + * + * Here operator+(GMat,GScalar) is used to wrap cv::gapi::addC() + * and a value-initialized GScalar is created on the fly. + * + * @overload + */ + GScalar(double v0); // Constant value constructor from double + + /// @private + GScalar(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GOrigin& priv(); // Internal use only + /// @private + const GOrigin& priv() const; // Internal use only + +private: + std::shared_ptr m_priv; +}; + +/** @} */ + +/** + * \addtogroup gapi_meta_args + * @{ + */ +struct GAPI_EXPORTS_W_SIMPLE GScalarDesc +{ + // NB.: right now it is empty + + inline bool operator== (const GScalarDesc &) const + { + return true; // NB: implement this method if GScalar meta appears + } + + inline bool operator!= (const GScalarDesc &rhs) const + { + return !(*this == rhs); + } +}; + +GAPI_EXPORTS_W inline GScalarDesc empty_scalar_desc() { return GScalarDesc(); } + +GAPI_EXPORTS GScalarDesc descr_of(const cv::Scalar &scalar); + +std::ostream& operator<<(std::ostream& os, const cv::GScalarDesc &desc); + +} // namespace cv + +#endif // OPENCV_GAPI_GSCALAR_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gstreaming.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gstreaming.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d413195b817865e36bd8b6fe4312c886c40f3ac6 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gstreaming.hpp @@ -0,0 +1,430 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_GSTREAMING_COMPILED_HPP +#define OPENCV_GAPI_GSTREAMING_COMPILED_HPP + +#include +#include + +#include +#include +#include +#include +#include + +namespace cv { + +template using optional = cv::util::optional; + +namespace detail { +template struct wref_spec { + using type = T; +}; +template struct wref_spec > { + using type = T; +}; + +template +struct OptRef { + struct OptHolder { + virtual void mov(RefHolder &h) = 0; + virtual void reset() = 0; + virtual ~OptHolder() = default; + using Ptr = std::shared_ptr; + }; + template struct Holder final: OptHolder { + std::reference_wrapper > m_opt_ref; + + explicit Holder(cv::optional& opt) : m_opt_ref(std::ref(opt)) { + } + virtual void mov(RefHolder &h) override { + using U = typename wref_spec::type; + m_opt_ref.get() = cv::util::make_optional(std::move(h.template wref())); + } + virtual void reset() override { + m_opt_ref.get().reset(); + } + }; + template + explicit OptRef(cv::optional& t) : m_opt{new Holder(t)} {} + void mov(RefHolder &h) { m_opt->mov(h); } + void reset() { m_opt->reset();} +private: + typename OptHolder::Ptr m_opt; +}; +using OptionalVectorRef = OptRef; +using OptionalOpaqueRef = OptRef; +} // namespace detail + +// TODO: Keep it in sync with GRunArgP (derive the type automatically?) +using GOptRunArgP = util::variant< + optional*, + optional*, + optional*, + optional*, + cv::detail::OptionalVectorRef, + cv::detail::OptionalOpaqueRef +>; +using GOptRunArgsP = std::vector; + +using GOptRunArg = util::variant< + optional, + optional, + optional, + optional, + optional, + optional +>; +using GOptRunArgs = std::vector; + +namespace detail { + +template inline GOptRunArgP wrap_opt_arg(optional& arg) { + // By default, T goes to an OpaqueRef. All other types are specialized + return GOptRunArgP{OptionalOpaqueRef(arg)}; +} + +template inline GOptRunArgP wrap_opt_arg(optional >& arg) { + return GOptRunArgP{OptionalVectorRef(arg)}; +} + +template<> inline GOptRunArgP wrap_opt_arg(optional &m) { + return GOptRunArgP{&m}; +} + +template<> inline GOptRunArgP wrap_opt_arg(optional &m) { + return GOptRunArgP{&m}; +} + +template<> inline GOptRunArgP wrap_opt_arg(optional &f) { + return GOptRunArgP{&f}; +} + +template<> inline GOptRunArgP wrap_opt_arg(optional &s) { + return GOptRunArgP{&s}; +} + +} // namespace detail + +// Now cv::gout() may produce an empty vector (see "dynamic graphs"), so +// there may be a conflict between these two. State here that Opt version +// _must_ have at least one input for this overload +template +inline GOptRunArgsP gout(optional&arg, optional&... args) +{ + return GOptRunArgsP{ detail::wrap_opt_arg(arg), detail::wrap_opt_arg(args)... }; +} + +/** + * \addtogroup gapi_main_classes + * @{ + */ +/** + * @brief Represents a computation (graph) compiled for streaming. + * + * This class represents a product of graph compilation (calling + * cv::GComputation::compileStreaming()). Objects of this class + * actually do stream processing, and the whole pipeline execution + * complexity is incapsulated into objects of this class. Execution + * model has two levels: at the very top, the execution of a + * heterogeneous graph is aggressively pipelined; at the very bottom + * the execution of every internal block is determined by its + * associated backend. Backends are selected based on kernel packages + * passed via compilation arguments ( see @ref gapi_compile_args, + * GNetworkPackage, GKernelPackage for details). + * + * GStreamingCompiled objects have a "player" semantics -- there are + * methods like start() and stop(). GStreamingCompiled has a full + * control over a videostream and so is stateful. You need to specify the + * input stream data using setSource() and then call start() to + * actually start processing. After that, use pull() or try_pull() to + * obtain next processed data frame from the graph in a blocking or + * non-blocking way, respectively. + * + * Currently a single GStreamingCompiled can process only one video + * streat at time. Produce multiple GStreamingCompiled objects to run the + * same graph on multiple video streams. + * + * @sa GCompiled + */ +class GAPI_EXPORTS_W_SIMPLE GStreamingCompiled +{ +public: + class GAPI_EXPORTS Priv; + GAPI_WRAP GStreamingCompiled(); + + // FIXME: More overloads? + /** + * @brief Specify the input data to GStreamingCompiled for + * processing, a generic version. + * + * Use gin() to create an input parameter vector. + * + * Input vectors must have the same number of elements as defined + * in the cv::GComputation protocol (at the moment of its + * construction). Shapes of elements also must conform to protocol + * (e.g. cv::Mat needs to be passed where cv::GMat has been + * declared as input, and so on). Run-time exception is generated + * on type mismatch. + * + * In contrast with regular GCompiled, user can also pass an + * object of type GVideoCapture for a GMat parameter of the parent + * GComputation. The compiled pipeline will start fetching data + * from that GVideoCapture and feeding it into the + * pipeline. Pipeline stops when a GVideoCapture marks end of the + * stream (or when stop() is called). + * + * Passing a regular Mat for a GMat parameter makes it "infinite" + * source -- pipeline may run forever feeding with this Mat until + * stopped explicitly. + * + * Currently only a single GVideoCapture is supported as input. If + * the parent GComputation is declared with multiple input GMat's, + * one of those can be specified as GVideoCapture but all others + * must be regular Mat objects. + * + * Throws if pipeline is already running. Use stop() and then + * setSource() to run the graph on a new video stream. + * + * @note This method is not thread-safe (with respect to the user + * side) at the moment. Protect the access if + * start()/stop()/setSource() may be called on the same object in + * multiple threads in your application. + * + * @param ins vector of inputs to process. + * @sa gin + */ + void setSource(GRunArgs &&ins); + + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP void setSource(const cv::detail::ExtractArgsCallback& callback); + + /** + * @brief Specify an input video stream for a single-input + * computation pipeline. + * + * Throws if pipeline is already running. Use stop() and then + * setSource() to run the graph on a new video stream. + * + * @overload + * @param s a shared pointer to IStreamSource representing the + * input video stream. + */ + void setSource(const gapi::wip::IStreamSource::Ptr& s); + + /** + * @brief Constructs and specifies an input video stream for a + * single-input computation pipeline with the given parameters. + * + * Throws if pipeline is already running. Use stop() and then + * setSource() to run the graph on a new video stream. + * + * @overload + * @param args arguments used to construct and initialize a stream + * source. + */ + template + void setSource(Args&&... args) { + setSource(cv::gapi::wip::make_src(std::forward(args)...)); + } + + /** + * @brief Start the pipeline execution. + * + * Use pull()/try_pull() to obtain data. Throws an exception if + * a video source was not specified. + * + * setSource() must be called first, even if the pipeline has been + * working already and then stopped (explicitly via stop() or due + * stream completion) + * + * @note This method is not thread-safe (with respect to the user + * side) at the moment. Protect the access if + * start()/stop()/setSource() may be called on the same object in + * multiple threads in your application. + */ + GAPI_WRAP void start(); + + /** + * @brief Get the next processed frame from the pipeline. + * + * Use gout() to create an output parameter vector. + * + * Output vectors must have the same number of elements as defined + * in the cv::GComputation protocol (at the moment of its + * construction). Shapes of elements also must conform to protocol + * (e.g. cv::Mat needs to be passed where cv::GMat has been + * declared as output, and so on). Run-time exception is generated + * on type mismatch. + * + * This method writes new data into objects passed via output + * vector. If there is no data ready yet, this method blocks. Use + * try_pull() if you need a non-blocking version. + * + * @param outs vector of output parameters to obtain. + * @return true if next result has been obtained, + * false marks end of the stream. + */ + bool pull(cv::GRunArgsP &&outs); + + // NB: Used from python + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP std::tuple> pull(); + + /** + * @brief Get some next available data from the pipeline. + * + * This method takes a vector of cv::optional object. An object is + * assigned to some value if this value is available (ready) at + * the time of the call, and resets the object to empty() if it is + * not. + * + * This is a blocking method which guarantees that some data has + * been written to the output vector on return. + * + * Using this method only makes sense if the graph has + * desynchronized parts (see cv::gapi::desync). If there is no + * desynchronized parts in the graph, the behavior of this + * method is identical to the regular pull() (all data objects are + * produced synchronously in the output vector). + * + * Use gout() to create an output parameter vector. + * + * Output vectors must have the same number of elements as defined + * in the cv::GComputation protocol (at the moment of its + * construction). Shapes of elements also must conform to protocol + * (e.g. cv::optional needs to be passed where cv::GMat + * has been declared as output, and so on). Run-time exception is + * generated on type mismatch. + * + * This method writes new data into objects passed via output + * vector. If there is no data ready yet, this method blocks. Use + * try_pull() if you need a non-blocking version. + * + * @param outs vector of output parameters to obtain. + * @return true if next result has been obtained, + * false marks end of the stream. + * + * @sa cv::gapi::desync + */ + bool pull(cv::GOptRunArgsP &&outs); + + /** + * @brief Try to get the next processed frame from the pipeline. + * + * Use gout() to create an output parameter vector. + * + * This method writes new data into objects passed via output + * vector. If there is no data ready yet, the output vector + * remains unchanged and false is returned. + * + * @return true if data has been obtained, and false if it was + * not. Note: false here doesn't mark the end of the stream. + */ + bool try_pull(cv::GRunArgsP &&outs); + + /** + * @brief Stop (abort) processing the pipeline. + * + * Note - it is not pause but a complete stop. Calling start() + * will cause G-API to start processing the stream from the early beginning. + * + * Throws if the pipeline is not running. + */ + GAPI_WRAP void stop(); + + /** + * @brief Test if the pipeline is running. + * + * @note This method is not thread-safe (with respect to the user + * side) at the moment. Protect the access if + * start()/stop()/setSource() may be called on the same object in + * multiple threads in your application. + * + * @return true if the current stream is not over yet. + */ + GAPI_WRAP bool running() const; + + /// @private + Priv& priv(); + + /** + * @brief Check if compiled object is valid (non-empty) + * + * @return true if the object is runnable (valid), false otherwise + */ + explicit operator bool () const; + + /** + * @brief Vector of metadata this graph was compiled for. + * + * @return Unless _reshape_ is not supported, return value is the + * same vector which was passed to cv::GComputation::compile() to + * produce this compiled object. Otherwise, it is the latest + * metadata vector passed to reshape() (if that call was + * successful). + */ + const GMetaArgs& metas() const; // Meta passed to compile() + + /** + * @brief Vector of metadata descriptions of graph outputs + * + * @return vector with formats/resolutions of graph's output + * objects, auto-inferred from input metadata vector by + * operations which form this computation. + * + * @note GCompiled objects produced from the same + * cv::GComputiation graph with different input metas may return + * different values in this vector. + */ + const GMetaArgs& outMetas() const; + +protected: + /// @private + std::shared_ptr m_priv; +}; + +namespace gapi { + +/** + * @brief This namespace contains G-API functions, structures, and + * symbols related to the Streaming execution mode. + * + * Some of the operations defined in this namespace (e.g. size(), + * BGR(), etc.) can be used in the traditional execution mode too. + */ +namespace streaming { +/** + * @brief Specify queue capacity for streaming execution. + * + * In the streaming mode the pipeline steps are connected with queues + * and this compile argument controls every queue's size. + */ +struct GAPI_EXPORTS_W_SIMPLE queue_capacity +{ + GAPI_WRAP + explicit queue_capacity(size_t cap = 1) : capacity(cap) { } + GAPI_PROP_RW + size_t capacity; +}; +} // namespace streaming +} // namespace gapi + +namespace detail +{ +template<> struct CompileArgTag +{ + static const char* tag() { return "gapi.queue_capacity"; } +}; +} + +/** @} gapi_main_classes */ + +} + +#endif // OPENCV_GAPI_GSTREAMING_COMPILED_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtransform.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtransform.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ce88c894d7f30faba86832c65c7dff921e40ebdf --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtransform.hpp @@ -0,0 +1,103 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_GTRANSFORM_HPP +#define OPENCV_GAPI_GTRANSFORM_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace cv +{ + +struct GAPI_EXPORTS GTransform +{ + // FIXME: consider another simplified + // class instead of GComputation + using F = std::function; + + std::string description; + F pattern; + F substitute; + + GTransform(const std::string& d, const F &p, const F &s) : description(d), pattern(p), substitute(s) {} +}; + +namespace detail +{ + +template +struct TransHelper; + +template +struct TransHelper, Out> +{ + template + static GComputation invoke(Callable f, Seq, Seq) + { + const std::tuple ins; + const auto r = tuple_wrap_helper::get(f(std::get(ins)...)); + return GComputation(cv::GIn(std::get(ins)...), + cv::GOut(std::get(r)...)); + } + + static GComputation get_pattern() + { + return invoke(K::pattern, typename MkSeq::type(), + typename MkSeq::type>::value>::type()); + } + static GComputation get_substitute() + { + return invoke(K::substitute, typename MkSeq::type(), + typename MkSeq::type>::value>::type()); + } +}; +} // namespace detail + +template +class GTransformImpl; + +template +class GTransformImpl> : public cv::detail::TransHelper, R>, + public cv::detail::TransformTag +{ +public: + // FIXME: currently there is no check that transformations' signatures are unique + // and won't be any intersection in graph compilation stage + using API = K; + + static GTransform transformation() + { + return GTransform(K::descr(), &K::get_pattern, &K::get_substitute); + } +}; +} // namespace cv + +#define G_DESCR_HELPER_CLASS(Class) Class##DescrHelper + +#define G_DESCR_HELPER_BODY(Class, Descr) \ + namespace detail \ + { \ + struct G_DESCR_HELPER_CLASS(Class) \ + { \ + static constexpr const char *descr() { return Descr; } \ + }; \ + } + +#define GAPI_TRANSFORM(Class, API, Descr) \ + G_DESCR_HELPER_BODY(Class, Descr) \ + struct Class final : public cv::GTransformImpl, \ + public detail::G_DESCR_HELPER_CLASS(Class) + +#endif // OPENCV_GAPI_GTRANSFORM_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtype_traits.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtype_traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c42d64a7617c50a712037d45f3c9025a95f9f368 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtype_traits.hpp @@ -0,0 +1,242 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP +#define OPENCV_GAPI_GTYPE_TRAITS_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cv +{ +namespace detail +{ + template + struct contains_shape_field : std::false_type {}; + + template + struct contains_shape_field> : + std::is_same::type, GShape> + {}; + + template + struct has_gshape : contains_shape_field {}; + + // FIXME: These traits and enum and possible numerous switch(kind) + // block may be replaced with a special Handler object or with + // a double dispatch + enum class ArgKind: int + { + OPAQUE_VAL, // Unknown, generic, opaque-to-GAPI data type - STATIC + // Note: OPAQUE is sometimes defined in Win sys headers +#if !defined(OPAQUE) && !defined(CV_DOXYGEN) + OPAQUE = OPAQUE_VAL, // deprecated value used for compatibility, use OPAQUE_VAL instead +#endif + GOBJREF, // reference to object + GMAT, // a cv::GMat + GMATP, // a cv::GMatP + GFRAME, // a cv::GFrame + GSCALAR, // a cv::GScalar + GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray!) + GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque!) + }; + + // Describe G-API types (G-types) with traits. Mostly used by + // cv::GArg to store meta information about types passed into + // operation arguments. Please note that cv::GComputation is + // defined on GProtoArgs, not GArgs! + template struct GTypeTraits; + template struct GTypeTraits + { + static constexpr const ArgKind kind = ArgKind::OPAQUE_VAL; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; + }; + template<> struct GTypeTraits + { + static constexpr const ArgKind kind = ArgKind::GMAT; + static constexpr const GShape shape = GShape::GMAT; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; + }; + template<> struct GTypeTraits + { + static constexpr const ArgKind kind = ArgKind::GMATP; + static constexpr const GShape shape = GShape::GMAT; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; + }; + template<> struct GTypeTraits + { + static constexpr const ArgKind kind = ArgKind::GFRAME; + static constexpr const GShape shape = GShape::GFRAME; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; + }; + template<> struct GTypeTraits + { + static constexpr const ArgKind kind = ArgKind::GSCALAR; + static constexpr const GShape shape = GShape::GSCALAR; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; + }; + template struct GTypeTraits > + { + static constexpr const ArgKind kind = ArgKind::GARRAY; + static constexpr const GShape shape = GShape::GARRAY; + static constexpr const OpaqueKind op_kind = GOpaqueTraits::kind; + using host_type = std::vector; + using strip_type = cv::detail::VectorRef; + static cv::detail::GArrayU wrap_value(const cv::GArray &t) { return t.strip();} + static cv::detail::VectorRef wrap_in (const std::vector &t) { return detail::VectorRef(t); } + static cv::detail::VectorRef wrap_out ( std::vector &t) { return detail::VectorRef(t); } + }; + template struct GTypeTraits > + { + static constexpr const ArgKind kind = ArgKind::GOPAQUE; + static constexpr const GShape shape = GShape::GOPAQUE; + static constexpr const OpaqueKind op_kind = GOpaqueTraits::kind; + using host_type = T; + using strip_type = cv::detail::OpaqueRef; + static cv::detail::GOpaqueU wrap_value(const cv::GOpaque &t) { return t.strip();} + static cv::detail::OpaqueRef wrap_in (const T &t) { return detail::OpaqueRef(t); } + static cv::detail::OpaqueRef wrap_out ( T &t) { return detail::OpaqueRef(t); } + }; + + // Tests if Trait for type T requires extra marshalling ("custom wrap") or not. + // If Traits has wrap_value() defined, it does. + template struct has_custom_wrap + { + template class check; + template static std::true_type test(check::wrap_value)> *); + template static std::false_type test(...); + using type = decltype(test(nullptr)); + static const constexpr bool value = std::is_same(nullptr))>::value; + }; + + // Resolve a Host type back to its associated G-Type. + // FIXME: Probably it can be avoided + // FIXME: GMatP is not present here. + // (Actually these traits is used only to check + // if associated G-type has custom wrap functions + // and GMat behavior is correct for GMatP) + template struct GTypeOf; +#if !defined(GAPI_STANDALONE) + template<> struct GTypeOf { using type = cv::GMat; }; +#endif // !defined(GAPI_STANDALONE) + template<> struct GTypeOf { using type = cv::GMat; }; + template<> struct GTypeOf { using type = cv::GMat; }; + template<> struct GTypeOf { using type = cv::GScalar; }; + template struct GTypeOf > { using type = cv::GArray; }; + template struct GTypeOf { using type = cv::GOpaque;}; + template<> struct GTypeOf { using type = cv::GFrame; }; + + // FIXME: This is not quite correct since IStreamSource may + // produce not only Mat but also MediaFrame, Scalar and vector + // data. TODO: Extend the type dispatching on these types too. + template<> struct GTypeOf { using type = cv::GMat;}; + template using g_type_of_t = typename GTypeOf::type; + + // Marshalling helper for G-types and its Host types. Helps G-API + // to store G types in internal generic containers for further + // processing. Implements the following callbacks: + // + // * wrap() - converts user-facing G-type into an internal one + // for internal storage. + // Used when G-API operation is instantiated (G::on(), + // etc) during expressing a pipeline. Mostly returns input + // value "as is" except the case when G-type is a template. For + // template G-classes, calls custom wrap() from Traits. + // The value returned by wrap() is then wrapped into GArg() and + // stored in G-API metadata. + // + // Example: + // - cv::GMat arguments are passed as-is. + // - integers, pointers, STL containers, user types are passed as-is. + // - cv::GArray is converted to cv::GArrayU. + // + // * wrap_in() / wrap_out() - convert Host type associated with + // G-type to internal representation type. + // + // - For "simple" (non-template) G-types, returns value as-is. + // Example: cv::GMat has host type cv::Mat, when user passes a + // cv::Mat, system stores it internally as cv::Mat. + // + // - For "complex" (template) G-types, utilizes custom + // wrap_in()/wrap_out() as described in Traits. + // Example: cv::GArray has host type std::vector, when + // user passes a std::vector, system stores it + // internally as VectorRef (with stripped away). + template struct WrapValue + { + static auto wrap(const T& t) -> + typename std::remove_reference::type + { + return static_cast::type>(t); + } + + template static U wrap_in (const U &u) { return u; } + template static U* wrap_out(U &u) { return &u; } + }; + template struct WrapValue::value>::type> + { + static auto wrap(const T& t) -> decltype(GTypeTraits::wrap_value(t)) + { + return GTypeTraits::wrap_value(t); + } + template static auto wrap_in (const U &u) -> typename GTypeTraits::strip_type + { + static_assert(!(cv::detail::has_gshape>::value + || cv::detail::contains::type, GAPI_OWN_TYPES_LIST>::value), + "gin/gout must not be used with G* classes or cv::gapi::own::*"); + return GTypeTraits::wrap_in(u); + } + template static auto wrap_out(U &u) -> typename GTypeTraits::strip_type + { + static_assert(!(cv::detail::has_gshape>::value + || cv::detail::contains::type, GAPI_OWN_TYPES_LIST>::value), + "gin/gout must not be used with G* classes or cv::gapi::own::*"); + return GTypeTraits::wrap_out(u); + } + }; + + template using wrap_gapi_helper = WrapValue::type>; + template using wrap_host_helper = WrapValue >::type>; + +// Union type for various user-defined type constructors (GArray, +// GOpaque, etc) +// +// TODO: Replace construct-only API with a more generic one (probably +// with bits of introspection) +// +// Not required for non-user-defined types (GMat, GScalar, etc) +using HostCtor = util::variant + < util::monostate + , detail::ConstructVec + , detail::ConstructOpaque + >; + +template struct GObtainCtor { + static HostCtor get() { return HostCtor{}; } +}; +template struct GObtainCtor > { + static HostCtor get() { return HostCtor{ConstructVec{&GArray::VCtor}}; } +}; +template struct GObtainCtor > { + static HostCtor get() { return HostCtor{ConstructOpaque{&GOpaque::Ctor}}; } +}; +} // namespace detail +} // namespace cv + +#endif // OPENCV_GAPI_GTYPE_TRAITS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtyped.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtyped.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2acc2f7ffbf06cf0e1d50fad268f68814ac4960a --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/gtyped.hpp @@ -0,0 +1,246 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GTYPED_HPP +#define OPENCV_GAPI_GTYPED_HPP +#if !defined(GAPI_STANDALONE) + +#include + +#include +#include +#include +#include + +namespace cv { + +namespace detail +{ + // FIXME: How to prevent coolhackers from extending it by their own types? + // FIXME: ...Should we care? + template struct ProtoToParam; + template<> struct ProtoToParam { using type = cv::Mat; }; + template<> struct ProtoToParam { using type = cv::Scalar; }; + template struct ProtoToParam > { using type = std::vector; }; + template<> struct ProtoToParam> { using type = std::vector; }; + template struct ProtoToParam > { using type = U; }; + template using ProtoToParamT = typename ProtoToParam::type; + + template struct ProtoToMeta; + template<> struct ProtoToMeta { using type = cv::GMatDesc; }; + template<> struct ProtoToMeta { using type = cv::GScalarDesc; }; + template struct ProtoToMeta > { using type = cv::GArrayDesc; }; + template struct ProtoToMeta > { using type = cv::GOpaqueDesc; }; + template using ProtoToMetaT = typename ProtoToMeta::type; + + //workaround for MSVC 19.0 bug + template + auto make_default()->decltype(T{}) {return {};} +} // detail + +/** + * @brief This class is a typed wrapper over a regular GComputation. + * + * `std::function<>`-like template parameter specifies the graph + * signature so methods so the object's constructor, methods like + * `apply()` and the derived `GCompiledT::operator()` also become + * typed. + * + * There is no need to use cv::gin() or cv::gout() modifiers with + * objects of this class. Instead, all input arguments are followed + * by all output arguments in the order from the template argument + * signature. + * + * Refer to the following example. Regular (untyped) code is written this way: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp Untyped_Example + * + * Here: + * + * - cv::GComputation object is created with a lambda constructor + * where it is defined as a two-input, one-output graph. + * + * - Its method `apply()` in fact takes arbitrary number of arguments + * (as vectors) so user can pass wrong number of inputs/outputs + * here. C++ compiler wouldn't notice that since the cv::GComputation + * API is polymorphic, and only a run-time error will be generated. + * + * Now the same code written with typed API: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp Typed_Example + * + * The key difference is: + * + * - Now the constructor lambda *must take* parameters and *must + * return* values as defined in the `GComputationT<>` signature. + * - Its method `apply()` does not require any extra specifiers to + * separate input arguments from the output ones + * - A `GCompiledT` (compilation product) takes input/output + * arguments with no extra specifiers as well. + */ +template class GComputationT; + +// Single return value implementation +template class GComputationT +{ +public: + typedef std::function Gen; + + class GCompiledT + { + private: + friend class GComputationT; + + cv::GCompiled m_comp; + + explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {} + + public: + GCompiledT() {} + + void operator()(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT &outArg) + { + m_comp(cv::gin(inArgs...), cv::gout(outArg)); + } + + explicit operator bool() const + { + return static_cast(m_comp); + } + }; + +private: + typedef std::pair Captured; + + Captured capture(const Gen& g, Args... args) + { + return Captured(g(args...), cv::GIn(args...)); + } + + Captured m_capture; + cv::GComputation m_comp; + +public: + GComputationT(const Gen &generator) + : m_capture(capture(generator, detail::make_default()...)) + , m_comp(cv::GProtoInputArgs(std::move(m_capture.second)), + cv::GOut(m_capture.first)) + { + } + + void apply(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT &outArg, + GCompileArgs &&args) + { + m_comp.apply(cv::gin(inArgs...), cv::gout(outArg), std::move(args)); + } + + void apply(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT &outArg) + { + apply(inArgs..., outArg, GCompileArgs()); + } + + + GCompiledT compile(detail::ProtoToMetaT... inDescs) + { + GMetaArgs inMetas = { GMetaArg(inDescs)... }; + return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs())); + } + + GCompiledT compile(detail::ProtoToMetaT... inDescs, GCompileArgs &&args) + { + GMetaArgs inMetas = { GMetaArg(inDescs)... }; + return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args))); + } +}; + +// Multiple (fixed) return value implementation. FIXME: How to avoid copy-paste? +template class GComputationT(Args...)> +{ +public: + typedef std::function(Args...)> Gen; + + class GCompiledT + { + private: + friend class GComputationT(Args...)>; + + cv::GCompiled m_comp; + explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {} + + public: + GCompiledT() {} + + void operator()(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT&... outArgs) + { + m_comp(cv::gin(inArgs...), cv::gout(outArgs...)); + } + + explicit operator bool() const + { + return static_cast(m_comp); + } + }; + +private: + typedef std::pair Captured; + + template + Captured capture(GProtoArgs &&args, const std::tuple &rr, detail::Seq) + { + return Captured(cv::GOut(std::get(rr)...).m_args, args); + } + + Captured capture(const Gen& g, Args... args) + { + return capture(cv::GIn(args...).m_args, g(args...), typename detail::MkSeq::type()); + } + + Captured m_capture; + cv::GComputation m_comp; + +public: + GComputationT(const Gen &generator) + : m_capture(capture(generator, detail::make_default()...)) + , m_comp(cv::GProtoInputArgs(std::move(m_capture.second)), + cv::GProtoOutputArgs(std::move(m_capture.first))) + { + } + + void apply(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT&... outArgs, + GCompileArgs &&args) + { + m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...), std::move(args)); + } + + void apply(detail::ProtoToParamT... inArgs, + detail::ProtoToParamT&... outArgs) + { + apply(inArgs..., outArgs..., GCompileArgs()); + } + + + GCompiledT compile(detail::ProtoToMetaT... inDescs) + { + GMetaArgs inMetas = { GMetaArg(inDescs)... }; + return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs())); + } + + GCompiledT compile(detail::ProtoToMetaT... inDescs, GCompileArgs &&args) + { + GMetaArgs inMetas = { GMetaArg(inDescs)... }; + return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args))); + } +}; + +} // namespace cv +#endif // !defined(GAPI_STANDALONE) +#endif // OPENCV_GAPI_GTYPED_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/imgproc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..96aaa5a447f5900a7768a0bd48c37d99cd354660 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/imgproc.hpp @@ -0,0 +1,1769 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_IMGPROC_HPP +#define OPENCV_GAPI_IMGPROC_HPP + +#include + +#include // std::tuple + +#include +#include +#include + + +/** \defgroup gapi_imgproc G-API Image processing functionality +@{ + @defgroup gapi_filters Graph API: Image filters + @defgroup gapi_colorconvert Graph API: Converting image from one color space to another + @defgroup gapi_feature Graph API: Image Feature Detection + @defgroup gapi_shape Graph API: Image Structural Analysis and Shape Descriptors + @defgroup gapi_transform Graph API: Image and channel composition functions +@} + */ + +namespace { +void validateFindingContoursMeta(const int depth, const int chan, const int mode) +{ + GAPI_Assert(chan == 1); + switch (mode) + { + case cv::RETR_CCOMP: + GAPI_Assert(depth == CV_8U || depth == CV_32S); + break; + case cv::RETR_FLOODFILL: + GAPI_Assert(depth == CV_32S); + break; + default: + GAPI_Assert(depth == CV_8U); + break; + } +} +} // anonymous namespace + +namespace cv { namespace gapi { + +/** + * @brief This namespace contains G-API Operation Types for OpenCV + * ImgProc module functionality. + */ +namespace imgproc { + using GMat2 = std::tuple; + using GMat3 = std::tuple; // FIXME: how to avoid this? + using GFindContoursOutput = std::tuple>,GArray>; + + G_TYPED_KERNEL(GFilter2D, , "org.opencv.imgproc.filters.filter2D") { + static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Point, Scalar, int, Scalar) { + return in.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GSepFilter, , "org.opencv.imgproc.filters.sepfilter") { + static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Mat, Point, Scalar, int, Scalar) { + return in.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GBoxFilter, , "org.opencv.imgproc.filters.boxfilter") { + static GMatDesc outMeta(GMatDesc in, int ddepth, Size, Point, bool, int, Scalar) { + return in.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GBlur, , "org.opencv.imgproc.filters.blur") { + static GMatDesc outMeta(GMatDesc in, Size, Point, int, Scalar) { + return in; + } + }; + + G_TYPED_KERNEL(GGaussBlur, , "org.opencv.imgproc.filters.gaussianBlur") { + static GMatDesc outMeta(GMatDesc in, Size, double, double, int, Scalar) { + return in; + } + }; + + G_TYPED_KERNEL(GMedianBlur, , "org.opencv.imgproc.filters.medianBlur") { + static GMatDesc outMeta(GMatDesc in, int) { + return in; + } + }; + + G_TYPED_KERNEL(GErode, , "org.opencv.imgproc.filters.erode") { + static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) { + return in; + } + }; + + G_TYPED_KERNEL(GDilate, , "org.opencv.imgproc.filters.dilate") { + static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) { + return in; + } + }; + + G_TYPED_KERNEL(GMorphologyEx, , + "org.opencv.imgproc.filters.morphologyEx") { + static GMatDesc outMeta(const GMatDesc &in, MorphTypes, Mat, Point, int, + BorderTypes, Scalar) { + return in; + } + }; + + G_TYPED_KERNEL(GSobel, , "org.opencv.imgproc.filters.sobel") { + static GMatDesc outMeta(GMatDesc in, int ddepth, int, int, int, double, double, int, Scalar) { + return in.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL_M(GSobelXY, , "org.opencv.imgproc.filters.sobelxy") { + static std::tuple outMeta(GMatDesc in, int ddepth, int, int, double, double, int, Scalar) { + return std::make_tuple(in.withDepth(ddepth), in.withDepth(ddepth)); + } + }; + + G_TYPED_KERNEL(GLaplacian, , + "org.opencv.imgproc.filters.laplacian") { + static GMatDesc outMeta(GMatDesc in, int ddepth, int, double, double, int) { + return in.withDepth(ddepth); + } + }; + + G_TYPED_KERNEL(GBilateralFilter, , + "org.opencv.imgproc.filters.bilateralfilter") { + static GMatDesc outMeta(GMatDesc in, int, double, double, int) { + return in; + } + }; + + G_TYPED_KERNEL(GEqHist, , "org.opencv.imgproc.equalizeHist") { + static GMatDesc outMeta(GMatDesc in) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GCanny, , "org.opencv.imgproc.feature.canny") { + static GMatDesc outMeta(GMatDesc in, double, double, int, bool) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GGoodFeatures, + (GMat,int,double,double,Mat,int,bool,double)>, + "org.opencv.imgproc.feature.goodFeaturesToTrack") { + static GArrayDesc outMeta(GMatDesc, int, double, double, const Mat&, int, bool, double) { + return empty_array_desc(); + } + }; + + using RetrMode = RetrievalModes; + using ContMethod = ContourApproximationModes; + G_TYPED_KERNEL(GFindContours, >(GMat,RetrMode,ContMethod,GOpaque)>, + "org.opencv.imgproc.shape.findContours") + { + static GArrayDesc outMeta(GMatDesc in, RetrMode mode, ContMethod, GOpaqueDesc) + { + validateFindingContoursMeta(in.depth, in.chan, mode); + return empty_array_desc(); + } + }; + + // FIXME oc: make default value offset = Point() + G_TYPED_KERNEL(GFindContoursNoOffset, >(GMat,RetrMode,ContMethod)>, + "org.opencv.imgproc.shape.findContoursNoOffset") + { + static GArrayDesc outMeta(GMatDesc in, RetrMode mode, ContMethod) + { + validateFindingContoursMeta(in.depth, in.chan, mode); + return empty_array_desc(); + } + }; + + G_TYPED_KERNEL(GFindContoursH,)>, + "org.opencv.imgproc.shape.findContoursH") + { + static std::tuple + outMeta(GMatDesc in, RetrMode mode, ContMethod, GOpaqueDesc) + { + validateFindingContoursMeta(in.depth, in.chan, mode); + return std::make_tuple(empty_array_desc(), empty_array_desc()); + } + }; + + // FIXME oc: make default value offset = Point() + G_TYPED_KERNEL(GFindContoursHNoOffset,, + "org.opencv.imgproc.shape.findContoursHNoOffset") + { + static std::tuple + outMeta(GMatDesc in, RetrMode mode, ContMethod) + { + validateFindingContoursMeta(in.depth, in.chan, mode); + return std::make_tuple(empty_array_desc(), empty_array_desc()); + } + }; + + G_TYPED_KERNEL(GBoundingRectMat, (GMat)>, + "org.opencv.imgproc.shape.boundingRectMat") { + static GOpaqueDesc outMeta(GMatDesc in) { + if (in.depth == CV_8U) + { + GAPI_Assert(in.chan == 1); + } + else + { + GAPI_Assert (in.depth == CV_32S || in.depth == CV_32F); + int amount = detail::checkVector(in, 2u); + GAPI_Assert(amount != -1 && + "Input Mat can't be described as vector of 2-dimentional points"); + } + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GBoundingRectVector32S, (GArray)>, + "org.opencv.imgproc.shape.boundingRectVector32S") { + static GOpaqueDesc outMeta(GArrayDesc) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GBoundingRectVector32F, (GArray)>, + "org.opencv.imgproc.shape.boundingRectVector32F") { + static GOpaqueDesc outMeta(GArrayDesc) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DMat, (GMat,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DMat") { + static GOpaqueDesc outMeta(GMatDesc in,DistanceTypes,double,double,double) { + int amount = detail::checkVector(in, 2u); + GAPI_Assert(amount != -1 && + "Input Mat can't be described as vector of 2-dimentional points"); + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector32S, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector32S") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector32F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector32F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector64F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector64F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DMat, (GMat,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DMat") { + static GOpaqueDesc outMeta(GMatDesc in,int,double,double,double) { + int amount = detail::checkVector(in, 3u); + GAPI_Assert(amount != -1 && + "Input Mat can't be described as vector of 3-dimentional points"); + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector32S, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector32S") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector32F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector32F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector64F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector64F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GBGR2RGB, , "org.opencv.imgproc.colorconvert.bgr2rgb") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GRGB2YUV, , "org.opencv.imgproc.colorconvert.rgb2yuv") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GYUV2RGB, , "org.opencv.imgproc.colorconvert.yuv2rgb") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GBGR2I420, , "org.opencv.imgproc.colorconvert.bgr2i420") { + static GMatDesc outMeta(GMatDesc in) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 3); + GAPI_Assert(in.size.height % 2 == 0); + return in.withType(in.depth, 1).withSize(Size(in.size.width, in.size.height * 3 / 2)); + } + }; + + G_TYPED_KERNEL(GRGB2I420, , "org.opencv.imgproc.colorconvert.rgb2i420") { + static GMatDesc outMeta(GMatDesc in) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 3); + GAPI_Assert(in.size.height % 2 == 0); + return in.withType(in.depth, 1).withSize(Size(in.size.width, in.size.height * 3 / 2)); + } + }; + + G_TYPED_KERNEL(GI4202BGR, , "org.opencv.imgproc.colorconvert.i4202bgr") { + static GMatDesc outMeta(GMatDesc in) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 1); + GAPI_Assert(in.size.height % 3 == 0); + return in.withType(in.depth, 3).withSize(Size(in.size.width, in.size.height * 2 / 3)); + } + }; + + G_TYPED_KERNEL(GI4202RGB, , "org.opencv.imgproc.colorconvert.i4202rgb") { + static GMatDesc outMeta(GMatDesc in) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 1); + GAPI_Assert(in.size.height % 3 == 0); + return in.withType(in.depth, 3).withSize(Size(in.size.width, in.size.height * 2 / 3)); + } + }; + + G_TYPED_KERNEL(GNV12toRGB, , "org.opencv.imgproc.colorconvert.nv12torgb") { + static GMatDesc outMeta(GMatDesc in_y, GMatDesc in_uv) { + GAPI_Assert(in_y.chan == 1); + GAPI_Assert(in_uv.chan == 2); + GAPI_Assert(in_y.depth == CV_8U); + GAPI_Assert(in_uv.depth == CV_8U); + // UV size should be aligned with Y + GAPI_Assert(in_y.size.width == 2 * in_uv.size.width); + GAPI_Assert(in_y.size.height == 2 * in_uv.size.height); + return in_y.withType(CV_8U, 3); // type will be CV_8UC3; + } + }; + + G_TYPED_KERNEL(GNV12toBGR, , "org.opencv.imgproc.colorconvert.nv12tobgr") { + static GMatDesc outMeta(GMatDesc in_y, GMatDesc in_uv) { + GAPI_Assert(in_y.chan == 1); + GAPI_Assert(in_uv.chan == 2); + GAPI_Assert(in_y.depth == CV_8U); + GAPI_Assert(in_uv.depth == CV_8U); + // UV size should be aligned with Y + GAPI_Assert(in_y.size.width == 2 * in_uv.size.width); + GAPI_Assert(in_y.size.height == 2 * in_uv.size.height); + return in_y.withType(CV_8U, 3); // type will be CV_8UC3; + } + }; + + G_TYPED_KERNEL(GRGB2Lab, , "org.opencv.imgproc.colorconvert.rgb2lab") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GBGR2LUV, , "org.opencv.imgproc.colorconvert.bgr2luv") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GLUV2BGR, , "org.opencv.imgproc.colorconvert.luv2bgr") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GYUV2BGR, , "org.opencv.imgproc.colorconvert.yuv2bgr") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GBGR2YUV, , "org.opencv.imgproc.colorconvert.bgr2yuv") { + static GMatDesc outMeta(GMatDesc in) { + return in; // type still remains CV_8UC3; + } + }; + + G_TYPED_KERNEL(GRGB2Gray, , "org.opencv.imgproc.colorconvert.rgb2gray") { + static GMatDesc outMeta(GMatDesc in) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GRGB2GrayCustom, , "org.opencv.imgproc.colorconvert.rgb2graycustom") { + static GMatDesc outMeta(GMatDesc in, float, float, float) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GBGR2Gray, , "org.opencv.imgproc.colorconvert.bgr2gray") { + static GMatDesc outMeta(GMatDesc in) { + return in.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GBayerGR2RGB, , "org.opencv.imgproc.colorconvert.bayergr2rgb") { + static cv::GMatDesc outMeta(cv::GMatDesc in) { + return in.withType(CV_8U, 3); + } + }; + + G_TYPED_KERNEL(GRGB2HSV, , "org.opencv.imgproc.colorconvert.rgb2hsv") { + static cv::GMatDesc outMeta(cv::GMatDesc in) { + return in; + } + }; + + G_TYPED_KERNEL(GRGB2YUV422, , "org.opencv.imgproc.colorconvert.rgb2yuv422") { + static cv::GMatDesc outMeta(cv::GMatDesc in) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 3); + return in.withType(in.depth, 2); + } + }; + + G_TYPED_KERNEL(GNV12toRGBp, , "org.opencv.imgproc.colorconvert.nv12torgbp") { + static GMatDesc outMeta(GMatDesc inY, GMatDesc inUV) { + GAPI_Assert(inY.depth == CV_8U); + GAPI_Assert(inUV.depth == CV_8U); + GAPI_Assert(inY.chan == 1); + GAPI_Assert(inY.planar == false); + GAPI_Assert(inUV.chan == 2); + GAPI_Assert(inUV.planar == false); + GAPI_Assert(inY.size.width == 2 * inUV.size.width); + GAPI_Assert(inY.size.height == 2 * inUV.size.height); + return inY.withType(CV_8U, 3).asPlanar(); + } + }; + + G_TYPED_KERNEL(GNV12toGray, , "org.opencv.imgproc.colorconvert.nv12togray") { + static GMatDesc outMeta(GMatDesc inY, GMatDesc inUV) { + GAPI_Assert(inY.depth == CV_8U); + GAPI_Assert(inUV.depth == CV_8U); + GAPI_Assert(inY.chan == 1); + GAPI_Assert(inY.planar == false); + GAPI_Assert(inUV.chan == 2); + GAPI_Assert(inUV.planar == false); + + GAPI_Assert(inY.size.width == 2 * inUV.size.width); + GAPI_Assert(inY.size.height == 2 * inUV.size.height); + return inY.withType(CV_8U, 1); + } + }; + + G_TYPED_KERNEL(GNV12toBGRp, , "org.opencv.imgproc.colorconvert.nv12tobgrp") { + static GMatDesc outMeta(GMatDesc inY, GMatDesc inUV) { + GAPI_Assert(inY.depth == CV_8U); + GAPI_Assert(inUV.depth == CV_8U); + GAPI_Assert(inY.chan == 1); + GAPI_Assert(inY.planar == false); + GAPI_Assert(inUV.chan == 2); + GAPI_Assert(inUV.planar == false); + GAPI_Assert(inY.size.width == 2 * inUV.size.width); + GAPI_Assert(inY.size.height == 2 * inUV.size.height); + return inY.withType(CV_8U, 3).asPlanar(); + } + }; + + G_TYPED_KERNEL(GResize, , "org.opencv.imgproc.transform.resize") { + static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int /*interp*/) { + if (sz.width != 0 && sz.height != 0) + { + return in.withSize(sz); + } + else + { + int outSz_w = saturate_cast(in.size.width * fx); + int outSz_h = saturate_cast(in.size.height * fy); + GAPI_Assert(outSz_w > 0 && outSz_h > 0); + return in.withSize(Size(outSz_w, outSz_h)); + } + } + }; + + G_TYPED_KERNEL(GResizeP, , "org.opencv.imgproc.transform.resizeP") { + static GMatDesc outMeta(GMatDesc in, Size sz, int interp) { + GAPI_Assert(in.depth == CV_8U); + GAPI_Assert(in.chan == 3); + GAPI_Assert(in.planar); + GAPI_Assert(interp == cv::INTER_LINEAR); + return in.withSize(sz); + } + }; + +} //namespace imgproc + +//! @addtogroup gapi_filters +//! @{ +/** @brief Applies a separable linear filter to a matrix(image). + +The function applies a separable linear filter to the matrix. That is, first, every row of src is +filtered with the 1D kernel kernelX. Then, every column of the result is filtered with the 1D +kernel kernelY. The final result is returned. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - In case of floating-point computation, rounding to nearest even is procedeed +if hardware supports it (if not - to nearest value). + - Function textual ID is "org.opencv.imgproc.filters.sepfilter" +@param src Source image. +@param ddepth desired depth of the destination image (the following combinations of src.depth() and ddepth are supported: + + src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F + src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F + src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F + src.depth() = CV_64F, ddepth = -1/CV_64F + +when ddepth=-1, the output image will have the same depth as the source) +@param kernelX Coefficients for filtering each row. +@param kernelY Coefficients for filtering each column. +@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor +is at the kernel center. +@param delta Value added to the filtered results before storing them. +@param borderType Pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa boxFilter, gaussianBlur, medianBlur + */ +GAPI_EXPORTS_W GMat sepFilter(const GMat& src, int ddepth, const Mat& kernelX, const Mat& kernelY, const Point& anchor /*FIXME: = Point(-1,-1)*/, + const Scalar& delta /*FIXME = GScalar(0)*/, int borderType = BORDER_DEFAULT, + const Scalar& borderValue = Scalar(0)); + +/** @brief Convolves an image with the kernel. + +The function applies an arbitrary linear filter to an image. When +the aperture is partially outside the image, the function interpolates outlier pixel values +according to the specified border mode. + +The function does actually compute correlation, not the convolution: + +\f[\texttt{dst} (x,y) = \sum _{ \substack{0\leq x' < \texttt{kernel.cols}\\{0\leq y' < \texttt{kernel.rows}}}} \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] + +That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip +the kernel using flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows - +anchor.y - 1)`. + +Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +Output image must have the same size and number of channels an input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.filter2D" + +@param src input image. +@param ddepth desired depth of the destination image +@param kernel convolution kernel (or rather a correlation kernel), a single-channel floating point +matrix; if you want to apply different kernels to different channels, split the image into +separate color planes using split and process them individually. +@param anchor anchor of the kernel that indicates the relative position of a filtered point within +the kernel; the anchor should lie within the kernel; default value (-1,-1) means that the anchor +is at the kernel center. +@param delta optional value added to the filtered pixels before storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa sepFilter + */ +GAPI_EXPORTS_W GMat filter2D(const GMat& src, int ddepth, const Mat& kernel, const Point& anchor = Point(-1,-1), const Scalar& delta = Scalar(0), + int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0)); + + +/** @brief Blurs an image using the box filter. + +The function smooths an image using the kernel: + +\f[\texttt{K} = \alpha \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \end{bmatrix}\f] + +where + +\f[\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true} \\1 & \texttt{otherwise} \end{cases}\f] + +Unnormalized box filter is useful for computing various integral characteristics over each pixel +neighborhood, such as covariance matrices of image derivatives (used in dense optical flow +algorithms, and so on). If you need to compute pixel sums over variable-size windows, use cv::integral. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.boxfilter" + +@param src Source image. +@param dtype the output image depth (-1 to set the input image data type). +@param ksize blurring kernel size. +@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor +is at the kernel center. +@param normalize flag, specifying whether the kernel is normalized by its area or not. +@param borderType Pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa sepFilter, gaussianBlur, medianBlur, integral + */ +GAPI_EXPORTS_W GMat boxFilter(const GMat& src, int dtype, const Size& ksize, const Point& anchor = Point(-1,-1), + bool normalize = true, int borderType = BORDER_DEFAULT, + const Scalar& borderValue = Scalar(0)); + +/** @brief Blurs an image using the normalized box filter. + +The function smooths an image using the kernel: + +\f[\texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix}\f] + +The call `blur(src, ksize, anchor, borderType)` is equivalent to `boxFilter(src, src.type(), ksize, anchor, +true, borderType)`. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.blur" + +@param src Source image. +@param ksize blurring kernel size. +@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel +center. +@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur + */ +GAPI_EXPORTS_W GMat blur(const GMat& src, const Size& ksize, const Point& anchor = Point(-1,-1), + int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0)); + + +//GAPI_EXPORTS_W void blur( InputArray src, OutputArray dst, + // Size ksize, Point anchor = Point(-1,-1), + // int borderType = BORDER_DEFAULT ); + + +/** @brief Blurs an image using a Gaussian filter. + +The function filter2Ds the source image with the specified Gaussian kernel. +Output image must have the same type and number of channels an input image. + +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.gaussianBlur" + +@param src input image; +@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be +positive and odd. Or, they can be zero's and then they are computed from sigma. +@param sigmaX Gaussian kernel standard deviation in X direction. +@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be +equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, +respectively (see cv::getGaussianKernel for details); to fully control the result regardless of +possible future modifications of all this semantics, it is recommended to specify all of ksize, +sigmaX, and sigmaY. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa sepFilter, boxFilter, medianBlur + */ +GAPI_EXPORTS_W GMat gaussianBlur(const GMat& src, const Size& ksize, double sigmaX, double sigmaY = 0, + int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0)); + +/** @brief Blurs an image using the median filter. + +The function smoothes an image using the median filter with the \f$\texttt{ksize} \times +\texttt{ksize}\f$ aperture. Each channel of a multi-channel image is processed independently. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. +The median filter uses cv::BORDER_REPLICATE internally to cope with border pixels, see cv::BorderTypes + - Function textual ID is "org.opencv.imgproc.filters.medianBlur" + +@param src input matrix (image) +@param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ... +@sa boxFilter, gaussianBlur + */ +GAPI_EXPORTS_W GMat medianBlur(const GMat& src, int ksize); + +/** @brief Erodes an image by using a specific structuring element. + +The function erodes the source image using the specified structuring element that determines the +shape of a pixel neighborhood over which the minimum is taken: + +\f[\texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f] + +Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently. +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.erode" + +@param src input image +@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular +structuring element is used. Kernel can be created using getStructuringElement. +@param anchor position of the anchor within the element; default value (-1, -1) means that the +anchor is at the element center. +@param iterations number of times erosion is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa dilate, morphologyEx + */ +GAPI_EXPORTS_W GMat erode(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue()); + +/** @brief Erodes an image by using 3 by 3 rectangular structuring element. + +The function erodes the source image using the rectangular structuring element with rectangle center as an anchor. +Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently. +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.erode" + +@param src input image +@param iterations number of times erosion is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa erode, dilate3x3 + */ +GAPI_EXPORTS_W GMat erode3x3(const GMat& src, int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue()); + +/** @brief Dilates an image by using a specific structuring element. + +The function dilates the source image using the specified structuring element that determines the +shape of a pixel neighborhood over which the maximum is taken: +\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f] + +Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently. +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.dilate" + +@param src input image. +@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular +structuring element is used. Kernel can be created using getStructuringElement +@param anchor position of the anchor within the element; default value (-1, -1) means that the +anchor is at the element center. +@param iterations number of times dilation is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa erode, morphologyEx, getStructuringElement + */ +GAPI_EXPORTS_W GMat dilate(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue()); + +/** @brief Dilates an image by using 3 by 3 rectangular structuring element. + +The function dilates the source image using the specified structuring element that determines the +shape of a pixel neighborhood over which the maximum is taken: +\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f] + +Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently. +Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1. +Output image must have the same type, size, and number of channels as the input image. +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.dilate" + +@param src input image. +@param iterations number of times dilation is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa dilate, erode3x3 + */ + +GAPI_EXPORTS_W GMat dilate3x3(const GMat& src, int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue()); + +/** @brief Performs advanced morphological transformations. + +The function can perform advanced morphological transformations using an erosion and dilation as +basic operations. + +Any of the operations can be done in-place. In case of multi-channel images, each channel is +processed independently. + +@note + - Function textual ID is "org.opencv.imgproc.filters.morphologyEx" + - The number of iterations is the number of times erosion or dilatation operation will be +applied. For instance, an opening operation (#MORPH_OPEN) with two iterations is equivalent to +apply successively: erode -> erode -> dilate -> dilate +(and not erode -> dilate -> erode -> dilate). + +@param src Input image. +@param op Type of a morphological operation, see #MorphTypes +@param kernel Structuring element. It can be created using #getStructuringElement. +@param anchor Anchor position within the element. Both negative values mean that the anchor is at +the kernel center. +@param iterations Number of times erosion and dilation are applied. +@param borderType Pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported. +@param borderValue Border value in case of a constant border. The default value has a special +meaning. +@sa dilate, erode, getStructuringElement + */ +GAPI_EXPORTS_W GMat morphologyEx(const GMat &src, const MorphTypes op, const Mat &kernel, + const Point &anchor = Point(-1,-1), + const int iterations = 1, + const BorderTypes borderType = BORDER_CONSTANT, + const Scalar &borderValue = morphologyDefaultBorderValue()); + +/** @brief Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. + +In all cases except one, the \f$\texttt{ksize} \times \texttt{ksize}\f$ separable kernel is used to +calculate the derivative. When \f$\texttt{ksize = 1}\f$, the \f$3 \times 1\f$ or \f$1 \times 3\f$ +kernel is used (that is, no Gaussian smoothing is done). `ksize = 1` can only be used for the first +or the second x- or y- derivatives. + +There is also the special value `ksize = FILTER_SCHARR (-1)` that corresponds to the \f$3\times3\f$ Scharr +filter that may give more accurate results than the \f$3\times3\f$ Sobel. The Scharr aperture is + +\f[\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}\f] + +for the x-derivative, or transposed for the y-derivative. + +The function calculates an image derivative by convolving the image with the appropriate kernel: + +\f[\texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}}\f] + +The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less +resistant to the noise. Most often, the function is called with ( xorder = 1, yorder = 0, ksize = 3) +or ( xorder = 0, yorder = 1, ksize = 3) to calculate the first x- or y- image derivative. The first +case corresponds to a kernel of: + +\f[\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}\f] + +The second case corresponds to a kernel of: + +\f[\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}\f] + +@note + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.sobel" + +@param src input image. +@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of + 8-bit input images it will result in truncated derivatives. +@param dx order of the derivative x. +@param dy order of the derivative y. +@param ksize size of the extended Sobel kernel; it must be odd. +@param scale optional scale factor for the computed derivative values; by default, no scaling is +applied (see cv::getDerivKernels for details). +@param delta optional delta value that is added to the results prior to storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa filter2D, gaussianBlur, cartToPolar + */ +GAPI_EXPORTS_W GMat Sobel(const GMat& src, int ddepth, int dx, int dy, int ksize = 3, + double scale = 1, double delta = 0, + int borderType = BORDER_DEFAULT, + const Scalar& borderValue = Scalar(0)); + +/** @brief Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. + +In all cases except one, the \f$\texttt{ksize} \times \texttt{ksize}\f$ separable kernel is used to +calculate the derivative. When \f$\texttt{ksize = 1}\f$, the \f$3 \times 1\f$ or \f$1 \times 3\f$ +kernel is used (that is, no Gaussian smoothing is done). `ksize = 1` can only be used for the first +or the second x- or y- derivatives. + +There is also the special value `ksize = FILTER_SCHARR (-1)` that corresponds to the \f$3\times3\f$ Scharr +filter that may give more accurate results than the \f$3\times3\f$ Sobel. The Scharr aperture is + +\f[\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}\f] + +for the x-derivative, or transposed for the y-derivative. + +The function calculates an image derivative by convolving the image with the appropriate kernel: + +\f[\texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}}\f] + +The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less +resistant to the noise. Most often, the function is called with ( xorder = 1, yorder = 0, ksize = 3) +or ( xorder = 0, yorder = 1, ksize = 3) to calculate the first x- or y- image derivative. The first +case corresponds to a kernel of: + +\f[\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}\f] + +The second case corresponds to a kernel of: + +\f[\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}\f] + +@note + - First returned matrix correspons to dx derivative while the second one to dy. + - Rounding to nearest even is procedeed if hardware supports it, if not - to nearest. + - Function textual ID is "org.opencv.imgproc.filters.sobelxy" + +@param src input image. +@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of + 8-bit input images it will result in truncated derivatives. +@param order order of the derivatives. +@param ksize size of the extended Sobel kernel; it must be odd. +@param scale optional scale factor for the computed derivative values; by default, no scaling is +applied (see cv::getDerivKernels for details). +@param delta optional delta value that is added to the results prior to storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of constant border type +@sa filter2D, gaussianBlur, cartToPolar + */ +GAPI_EXPORTS_W std::tuple SobelXY(const GMat& src, int ddepth, int order, int ksize = 3, + double scale = 1, double delta = 0, + int borderType = BORDER_DEFAULT, + const Scalar& borderValue = Scalar(0)); + +/** @brief Calculates the Laplacian of an image. + +The function calculates the Laplacian of the source image by adding up the second x and y +derivatives calculated using the Sobel operator: + +\f[\texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2}\f] + +This is done when `ksize > 1`. When `ksize == 1`, the Laplacian is computed by filtering the image +with the following \f$3 \times 3\f$ aperture: + +\f[\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}\f] + +@note Function textual ID is "org.opencv.imgproc.filters.laplacian" + +@param src Source image. +@param ddepth Desired depth of the destination image. +@param ksize Aperture size used to compute the second-derivative filters. See #getDerivKernels for +details. The size must be positive and odd. +@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is +applied. See #getDerivKernels for details. +@param delta Optional delta value that is added to the results prior to storing them in dst . +@param borderType Pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported. +@return Destination image of the same size and the same number of channels as src. +@sa Sobel, Scharr + */ +GAPI_EXPORTS_W GMat Laplacian(const GMat& src, int ddepth, int ksize = 1, + double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT); + +/** @brief Applies the bilateral filter to an image. + +The function applies bilateral filtering to the input image, as described in +http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html +bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is +very slow compared to most filters. + +_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\< +10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very +strong effect, making the image look "cartoonish". + +_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time +applications, and perhaps d=9 for offline applications that need heavy noise filtering. + +This filter does not work inplace. + +@note Function textual ID is "org.opencv.imgproc.filters.bilateralfilter" + +@param src Source 8-bit or floating-point, 1-channel or 3-channel image. +@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive, +it is computed from sigmaSpace. +@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that +farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting +in larger areas of semi-equal color. +@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that +farther pixels will influence each other as long as their colors are close enough (see sigmaColor +). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is +proportional to sigmaSpace. +@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes +@return Destination image of the same size and type as src. + */ +GAPI_EXPORTS_W GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace, + int borderType = BORDER_DEFAULT); + +//! @} gapi_filters + +//! @addtogroup gapi_feature +//! @{ +/** @brief Finds edges in an image using the Canny algorithm. + +The function finds edges in the input image and marks them in the output map edges using the +Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The +largest value is used to find initial segments of strong edges. See + + +@note Function textual ID is "org.opencv.imgproc.feature.canny" + +@param image 8-bit input image. +@param threshold1 first threshold for the hysteresis procedure. +@param threshold2 second threshold for the hysteresis procedure. +@param apertureSize aperture size for the Sobel operator. +@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm +\f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude ( +L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough ( +L2gradient=false ). + */ +GAPI_EXPORTS_W GMat Canny(const GMat& image, double threshold1, double threshold2, + int apertureSize = 3, bool L2gradient = false); + +/** @brief Determines strong corners on an image. + +The function finds the most prominent corners in the image or in the specified image region, as +described in @cite Shi94 + +- Function calculates the corner quality measure at every source image pixel using the + #cornerMinEigenVal or #cornerHarris . +- Function performs a non-maximum suppression (the local maximums in *3 x 3* neighborhood are + retained). +- The corners with the minimal eigenvalue less than + \f$\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)\f$ are rejected. +- The remaining corners are sorted by the quality measure in the descending order. +- Function throws away each corner for which there is a stronger corner at a distance less than + maxDistance. + +The function can be used to initialize a point-based tracker of an object. + +@note + - If the function is called with different values A and B of the parameter qualityLevel , and +A \> B, the vector of returned corners with qualityLevel=A will be the prefix of the output vector +with qualityLevel=B . + - Function textual ID is "org.opencv.imgproc.feature.goodFeaturesToTrack" + +@param image Input 8-bit or floating-point 32-bit, single-channel image. +@param maxCorners Maximum number of corners to return. If there are more corners than are found, +the strongest of them is returned. `maxCorners <= 0` implies that no limit on the maximum is set +and all detected corners are returned. +@param qualityLevel Parameter characterizing the minimal accepted quality of image corners. The +parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue +(see #cornerMinEigenVal ) or the Harris function response (see #cornerHarris ). The corners with the +quality measure less than the product are rejected. For example, if the best corner has the +quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure +less than 15 are rejected. +@param minDistance Minimum possible Euclidean distance between the returned corners. +@param mask Optional region of interest. If the image is not empty (it needs to have the type +CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected. +@param blockSize Size of an average block for computing a derivative covariation matrix over each +pixel neighborhood. See cornerEigenValsAndVecs . +@param useHarrisDetector Parameter indicating whether to use a Harris detector (see #cornerHarris) +or #cornerMinEigenVal. +@param k Free parameter of the Harris detector. + +@return vector of detected corners. + */ +GAPI_EXPORTS_W GArray goodFeaturesToTrack(const GMat &image, + int maxCorners, + double qualityLevel, + double minDistance, + const Mat &mask = Mat(), + int blockSize = 3, + bool useHarrisDetector = false, + double k = 0.04); + +/** @brief Equalizes the histogram of a grayscale image. + +//! @} gapi_feature + +The function equalizes the histogram of the input image using the following algorithm: + +- Calculate the histogram \f$H\f$ for src . +- Normalize the histogram so that the sum of histogram bins is 255. +- Compute the integral of the histogram: +\f[H'_i = \sum _{0 \le j < i} H(j)\f] +- Transform the image using \f$H'\f$ as a look-up table: \f$\texttt{dst}(x,y) = H'(\texttt{src}(x,y))\f$ + +The algorithm normalizes the brightness and increases the contrast of the image. +@note + - The returned image is of the same size and type as input. + - Function textual ID is "org.opencv.imgproc.equalizeHist" + +@param src Source 8-bit single channel image. + */ +GAPI_EXPORTS_W GMat equalizeHist(const GMat& src); + +//! @addtogroup gapi_shape +//! @{ +/** @brief Finds contours in a binary image. + +The function retrieves contours from the binary image using the algorithm @cite Suzuki85 . +The contours are a useful tool for shape analysis and object detection and recognition. +See squares.cpp in the OpenCV sample directory. + +@note Function textual ID is "org.opencv.imgproc.shape.findContours" + +@param src Input gray-scale image @ref CV_8UC1. Non-zero pixels are treated as 1's. Zero +pixels remain 0's, so the image is treated as binary . You can use #compare, #inRange, #threshold , +#adaptiveThreshold, #Canny, and others to create a binary image out of a grayscale or color one. +If mode equals to #RETR_CCOMP, the input can also be a 32-bit integer +image of labels ( @ref CV_32SC1 ). If #RETR_FLOODFILL then @ref CV_32SC1 is supported only. +@param mode Contour retrieval mode, see #RetrievalModes +@param method Contour approximation method, see #ContourApproximationModes +@param offset Optional offset by which every contour point is shifted. This is useful if the +contours are extracted from the image ROI and then they should be analyzed in the whole image +context. + +@return GArray of detected contours. Each contour is stored as a GArray of points. + */ +GAPI_EXPORTS GArray> +findContours(const GMat &src, const RetrievalModes mode, const ContourApproximationModes method, + const GOpaque &offset); + +// FIXME oc: make default value offset = Point() +/** @overload +@note Function textual ID is "org.opencv.imgproc.shape.findContoursNoOffset" + */ +GAPI_EXPORTS GArray> +findContours(const GMat &src, const RetrievalModes mode, const ContourApproximationModes method); + +/** @brief Finds contours and their hierarchy in a binary image. + +The function retrieves contours from the binary image using the algorithm @cite Suzuki85 +and calculates their hierarchy. +The contours are a useful tool for shape analysis and object detection and recognition. +See squares.cpp in the OpenCV sample directory. + +@note Function textual ID is "org.opencv.imgproc.shape.findContoursH" + +@param src Input gray-scale image @ref CV_8UC1. Non-zero pixels are treated as 1's. Zero +pixels remain 0's, so the image is treated as binary . You can use #compare, #inRange, #threshold , +#adaptiveThreshold, #Canny, and others to create a binary image out of a grayscale or color one. +If mode equals to #RETR_CCOMP, the input can also be a 32-bit integer +image of labels ( @ref CV_32SC1 ). If #RETR_FLOODFILL -- @ref CV_32SC1 supports only. +@param mode Contour retrieval mode, see #RetrievalModes +@param method Contour approximation method, see #ContourApproximationModes +@param offset Optional offset by which every contour point is shifted. This is useful if the +contours are extracted from the image ROI and then they should be analyzed in the whole image +context. + +@return + - GArray of detected contours. Each contour is stored as a GArray of points. + - Optional output GArray of cv::Vec4i, containing information about the image topology. +It has as many elements as the number of contours. For each i-th contour contours[i], the elements +hierarchy[i][0] , hierarchy[i][1] , hierarchy[i][2] , and hierarchy[i][3] are set to 0-based +indices in contours of the next and previous contours at the same hierarchical level, the first +child contour and the parent contour, respectively. If for the contour i there are no next, +previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative. + */ +GAPI_EXPORTS std::tuple>,GArray> +findContoursH(const GMat &src, const RetrievalModes mode, const ContourApproximationModes method, + const GOpaque &offset); + +// FIXME oc: make default value offset = Point() +/** @overload +@note Function textual ID is "org.opencv.imgproc.shape.findContoursHNoOffset" + */ +GAPI_EXPORTS std::tuple>,GArray> +findContoursH(const GMat &src, const RetrievalModes mode, const ContourApproximationModes method); + +/** @brief Calculates the up-right bounding rectangle of a point set or non-zero pixels +of gray-scale image. + +The function calculates and returns the minimal up-right bounding rectangle for the specified +point set or non-zero pixels of gray-scale image. + +@note + - Function textual ID is "org.opencv.imgproc.shape.boundingRectMat" + - In case of a 2D points' set given, Mat should be 2-dimensional, have a single row or column +if there are 2 channels, or have 2 columns if there is a single channel. Mat should have either +@ref CV_32S or @ref CV_32F depth + +@param src Input gray-scale image @ref CV_8UC1; or input set of @ref CV_32S or @ref CV_32F +2D points stored in Mat. + */ +GAPI_EXPORTS_W GOpaque boundingRect(const GMat& src); + +/** @overload + +Calculates the up-right bounding rectangle of a point set. + +@note Function textual ID is "org.opencv.imgproc.shape.boundingRectVector32S" + +@param src Input 2D point set, stored in std::vector. + */ +GAPI_EXPORTS_W GOpaque boundingRect(const GArray& src); + +/** @overload + +Calculates the up-right bounding rectangle of a point set. + +@note Function textual ID is "org.opencv.imgproc.shape.boundingRectVector32F" + +@param src Input 2D point set, stored in std::vector. + */ +GAPI_EXPORTS_W GOpaque boundingRect(const GArray& src); + +/** @brief Fits a line to a 2D point set. + +The function fits a line to a 2D point set by minimizing \f$\sum_i \rho(r_i)\f$ where +\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance +function, one of the following: +- DIST_L2 +\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f] +- DIST_L1 +\f[\rho (r) = r\f] +- DIST_L12 +\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f] +- DIST_FAIR +\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f] +- DIST_WELSCH +\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f] +- DIST_HUBER +\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] + +The algorithm is based on the M-estimator ( ) technique +that iteratively fits the line using the weighted least-squares algorithm. After each iteration the +weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . + +@note + - Function textual ID is "org.opencv.imgproc.shape.fitLine2DMat" + - In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row +or column if there are N channels, or have N columns if there is a single channel. + +@param src Input set of 2D points stored in one of possible containers: Mat, +std::vector, std::vector, std::vector. +@param distType Distance used by the M-estimator, see #DistanceTypes. @ref DIST_USER +and @ref DIST_C are not supported. +@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value +is chosen. +@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the +line). 1.0 would be a good default value for reps. If it is 0, a default value is chosen. +@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for aeps. +If it is 0, a default value is chosen. + +@return Output line parameters: a vector of 4 elements (like Vec4f) - (vx, vy, x0, y0), +where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line. + */ +GAPI_EXPORTS GOpaque fitLine2D(const GMat& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector32S" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector32F" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector64F" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @brief Fits a line to a 3D point set. + +The function fits a line to a 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where +\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance +function, one of the following: +- DIST_L2 +\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f] +- DIST_L1 +\f[\rho (r) = r\f] +- DIST_L12 +\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f] +- DIST_FAIR +\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f] +- DIST_WELSCH +\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f] +- DIST_HUBER +\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] + +The algorithm is based on the M-estimator ( ) technique +that iteratively fits the line using the weighted least-squares algorithm. After each iteration the +weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . + +@note + - Function textual ID is "org.opencv.imgproc.shape.fitLine3DMat" + - In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row +or column if there are N channels, or have N columns if there is a single channel. + +@param src Input set of 3D points stored in one of possible containers: Mat, +std::vector, std::vector, std::vector. +@param distType Distance used by the M-estimator, see #DistanceTypes. @ref DIST_USER +and @ref DIST_C are not supported. +@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value +is chosen. +@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the +line). 1.0 would be a good default value for reps. If it is 0, a default value is chosen. +@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for aeps. +If it is 0, a default value is chosen. + +@return Output line parameters: a vector of 6 elements (like Vec6f) - (vx, vy, vz, x0, y0, z0), +where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0, z0) is a point on +the line. + */ +GAPI_EXPORTS GOpaque fitLine3D(const GMat& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector32S" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector32F" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector64F" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +//! @} gapi_shape + +//! @addtogroup gapi_colorconvert +//! @{ +/** @brief Converts an image from BGR color space to RGB color space. + +The function converts an input image from BGR color space to RGB. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image is 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2rgb" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa RGB2BGR +*/ +GAPI_EXPORTS_W GMat BGR2RGB(const GMat& src); + +/** @brief Converts an image from RGB color space to gray-scaled. + +The conventional ranges for R, G, and B channel values are 0 to 255. +Resulting gray color value computed as +\f[\texttt{dst} (I)= \texttt{0.299} * \texttt{src}(I).R + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.114} * \texttt{src}(I).B \f] + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2gray" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1. +@sa RGB2YUV + */ +GAPI_EXPORTS_W GMat RGB2Gray(const GMat& src); + +/** @overload +Resulting gray color value computed as +\f[\texttt{dst} (I)= \texttt{rY} * \texttt{src}(I).R + \texttt{gY} * \texttt{src}(I).G + \texttt{bY} * \texttt{src}(I).B \f] + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2graycustom" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1. +@param rY float multiplier for R channel. +@param gY float multiplier for G channel. +@param bY float multiplier for B channel. +@sa RGB2YUV + */ +GAPI_EXPORTS_W GMat RGB2Gray(const GMat& src, float rY, float gY, float bY); + +/** @brief Converts an image from BGR color space to gray-scaled. + +The conventional ranges for B, G, and R channel values are 0 to 255. +Resulting gray color value computed as +\f[\texttt{dst} (I)= \texttt{0.114} * \texttt{src}(I).B + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.299} * \texttt{src}(I).R \f] + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2gray" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1. +@sa BGR2LUV + */ +GAPI_EXPORTS_W GMat BGR2Gray(const GMat& src); + +/** @brief Converts an image from RGB color space to YUV color space. + +The function converts an input image from RGB color space to YUV. +The conventional ranges for R, G, and B channel values are 0 to 255. + +In case of linear transformations, the range does not matter. But in case of a non-linear +transformation, an input RGB image should be normalized to the proper value range to get the correct +results, like here, at RGB \f$\rightarrow\f$ Y\*u\*v\* transformation. +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2yuv" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa YUV2RGB, RGB2Lab +*/ +GAPI_EXPORTS_W GMat RGB2YUV(const GMat& src); + +/** @brief Converts an image from BGR color space to I420 color space. + +The function converts an input image from BGR color space to I420. +The conventional ranges for R, G, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 1-channel image. @ref CV_8UC1. +Width of I420 output image must be the same as width of input image. +Height of I420 output image must be equal 3/2 from height of input image. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2i420" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa I4202BGR +*/ +GAPI_EXPORTS_W GMat BGR2I420(const GMat& src); + +/** @brief Converts an image from RGB color space to I420 color space. + +The function converts an input image from RGB color space to I420. +The conventional ranges for R, G, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 1-channel image. @ref CV_8UC1. +Width of I420 output image must be the same as width of input image. +Height of I420 output image must be equal 3/2 from height of input image. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2i420" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa I4202RGB +*/ +GAPI_EXPORTS_W GMat RGB2I420(const GMat& src); + +/** @brief Converts an image from I420 color space to BGR color space. + +The function converts an input image from I420 color space to BGR. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image. @ref CV_8UC3. +Width of BGR output image must be the same as width of input image. +Height of BGR output image must be equal 2/3 from height of input image. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.i4202bgr" + +@param src input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@sa BGR2I420 +*/ +GAPI_EXPORTS_W GMat I4202BGR(const GMat& src); + +/** @brief Converts an image from I420 color space to BGR color space. + +The function converts an input image from I420 color space to BGR. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image. @ref CV_8UC3. +Width of RGB output image must be the same as width of input image. +Height of RGB output image must be equal 2/3 from height of input image. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.i4202rgb" + +@param src input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@sa RGB2I420 +*/ +GAPI_EXPORTS_W GMat I4202RGB(const GMat& src); + +/** @brief Converts an image from BGR color space to LUV color space. + +The function converts an input image from BGR color space to LUV. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2luv" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa RGB2Lab, RGB2LUV +*/ +GAPI_EXPORTS_W GMat BGR2LUV(const GMat& src); + +/** @brief Converts an image from LUV color space to BGR color space. + +The function converts an input image from LUV color space to BGR. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.luv2bgr" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa BGR2LUV +*/ +GAPI_EXPORTS_W GMat LUV2BGR(const GMat& src); + +/** @brief Converts an image from YUV color space to BGR color space. + +The function converts an input image from YUV color space to BGR. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2bgr" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa BGR2YUV +*/ +GAPI_EXPORTS_W GMat YUV2BGR(const GMat& src); + +/** @brief Converts an image from BGR color space to YUV color space. + +The function converts an input image from BGR color space to YUV. +The conventional ranges for B, G, and R channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2yuv" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@sa YUV2BGR +*/ +GAPI_EXPORTS_W GMat BGR2YUV(const GMat& src); + +/** @brief Converts an image from RGB color space to Lab color space. + +The function converts an input image from BGR color space to Lab. +The conventional ranges for R, G, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC1. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2lab" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1. +@sa RGB2YUV, RGB2LUV +*/ +GAPI_EXPORTS_W GMat RGB2Lab(const GMat& src); + +/** @brief Converts an image from YUV color space to RGB. +The function converts an input image from YUV color space to RGB. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2rgb" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. + +@sa RGB2Lab, RGB2YUV +*/ +GAPI_EXPORTS_W GMat YUV2RGB(const GMat& src); + +/** @brief Converts an image from NV12 (YUV420p) color space to RGB. +The function converts an input image from NV12 color space to RGB. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgb" + +@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2. + +@sa YUV2RGB, NV12toBGR +*/ +GAPI_EXPORTS_W GMat NV12toRGB(const GMat& src_y, const GMat& src_uv); + +/** @brief Converts an image from NV12 (YUV420p) color space to gray-scaled. +The function converts an input image from NV12 color space to gray-scaled. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned 1-channel image @ref CV_8UC1. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12togray" + +@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2. + +@sa YUV2RGB, NV12toBGR +*/ +GAPI_EXPORTS_W GMat NV12toGray(const GMat& src_y, const GMat& src_uv); + +/** @brief Converts an image from NV12 (YUV420p) color space to BGR. +The function converts an input image from NV12 color space to RGB. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12tobgr" + +@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2. + +@sa YUV2BGR, NV12toRGB +*/ +GAPI_EXPORTS_W GMat NV12toBGR(const GMat& src_y, const GMat& src_uv); + +/** @brief Converts an image from BayerGR color space to RGB. +The function converts an input image from BayerGR color space to RGB. +The conventional ranges for G, R, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.bayergr2rgb" + +@param src_gr input image: 8-bit unsigned 1-channel image @ref CV_8UC1. + +@sa YUV2BGR, NV12toRGB +*/ +GAPI_EXPORTS_W GMat BayerGR2RGB(const GMat& src_gr); + +/** @brief Converts an image from RGB color space to HSV. +The function converts an input image from RGB color space to HSV. +The conventional ranges for R, G, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2hsv" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. + +@sa YUV2BGR, NV12toRGB +*/ +GAPI_EXPORTS_W GMat RGB2HSV(const GMat& src); + +/** @brief Converts an image from RGB color space to YUV422. +The function converts an input image from RGB color space to YUV422. +The conventional ranges for R, G, and B channel values are 0 to 255. + +Output image must be 8-bit unsigned 2-channel image @ref CV_8UC2. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2yuv422" + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. + +@sa YUV2BGR, NV12toRGB +*/ +GAPI_EXPORTS_W GMat RGB2YUV422(const GMat& src); + +/** @brief Converts an image from NV12 (YUV420p) color space to RGB. +The function converts an input image from NV12 color space to RGB. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned planar 3-channel image @ref CV_8UC1. +Planar image memory layout is three planes laying in the memory contiguously, +so the image height should be plane_height*plane_number, +image type is @ref CV_8UC1. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgbp" + +@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2. + +@sa YUV2RGB, NV12toBGRp, NV12toRGB +*/ +GAPI_EXPORTS GMatP NV12toRGBp(const GMat &src_y, const GMat &src_uv); + +/** @brief Converts an image from NV12 (YUV420p) color space to BGR. +The function converts an input image from NV12 color space to BGR. +The conventional ranges for Y, U, and V channel values are 0 to 255. + +Output image must be 8-bit unsigned planar 3-channel image @ref CV_8UC1. +Planar image memory layout is three planes laying in the memory contiguously, +so the image height should be plane_height*plane_number, +image type is @ref CV_8UC1. + +@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgbp" + +@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2. + +@sa YUV2RGB, NV12toRGBp, NV12toBGR +*/ +GAPI_EXPORTS GMatP NV12toBGRp(const GMat &src_y, const GMat &src_uv); + +//! @} gapi_colorconvert +//! @addtogroup gapi_transform +//! @{ +/** @brief Resizes an image. + +The function resizes the image src down to or up to the specified size. + +Output image size will have the size dsize (when dsize is non-zero) or the size computed from +src.size(), fx, and fy; the depth of output is the same as of src. + +If you want to resize src so that it fits the pre-created dst, +you may call the function as follows: +@code + // explicitly specify dsize=dst.size(); fx and fy will be computed from that. + resize(src, dst, dst.size(), 0, 0, interpolation); +@endcode +If you want to decimate the image by factor of 2 in each direction, you can call the function this +way: +@code + // specify fx and fy and let the function compute the destination image size. + resize(src, dst, Size(), 0.5, 0.5, interpolation); +@endcode +To shrink an image, it will generally look best with cv::INTER_AREA interpolation, whereas to +enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv::INTER_LINEAR +(faster but still looks OK). + +@note Function textual ID is "org.opencv.imgproc.transform.resize" + +@param src input image. +@param dsize output image size; if it equals zero, it is computed as: + \f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f] + Either dsize or both fx and fy must be non-zero. +@param fx scale factor along the horizontal axis; when it equals 0, it is computed as +\f[\texttt{(double)dsize.width/src.cols}\f] +@param fy scale factor along the vertical axis; when it equals 0, it is computed as +\f[\texttt{(double)dsize.height/src.rows}\f] +@param interpolation interpolation method, see cv::InterpolationFlags + +@sa warpAffine, warpPerspective, remap, resizeP + */ +GAPI_EXPORTS_W GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR); + +/** @brief Resizes a planar image. + +The function resizes the image src down to or up to the specified size. +Planar image memory layout is three planes laying in the memory contiguously, +so the image height should be plane_height*plane_number, image type is @ref CV_8UC1. + +Output image size will have the size dsize, the depth of output is the same as of src. + +@note Function textual ID is "org.opencv.imgproc.transform.resizeP" + +@param src input image, must be of @ref CV_8UC1 type; +@param dsize output image size; +@param interpolation interpolation method, only cv::INTER_LINEAR is supported at the moment + +@sa warpAffine, warpPerspective, remap, resize + */ +GAPI_EXPORTS GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation = cv::INTER_LINEAR); + +//! @} gapi_transform +} //namespace gapi +} //namespace cv + +#endif // OPENCV_GAPI_IMGPROC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..abbd32ba206314fa76377f69a16ed84651cd6fd2 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer.hpp @@ -0,0 +1,717 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_INFER_HPP +#define OPENCV_GAPI_INFER_HPP + +// FIXME: Inference API is currently only available in full mode +#if !defined(GAPI_STANDALONE) + +#include +#include // string +#include // tuple +#include // is_same, false_type + +#include // all_satisfy +#include // any<> +#include // GKernelType[M], GBackend +#include // GArg +#include // CompileArgTag +#include // GMetaArg + +namespace cv { + +template class GNetworkType; + +namespace detail { + +// Infer /////////////////////////////////////////////////////////////////////// +template +struct accepted_infer_types { + static constexpr const auto value = + std::is_same::type, cv::GMat>::value + || std::is_same::type, cv::GFrame>::value; +}; + +template +using valid_infer_types = all_satisfy; + +// Infer2 ////////////////////////////////////////////////////////////////////// + +template +struct valid_infer2_types; + +// Terminal case 1 (50/50 success) +template +struct valid_infer2_types< std::tuple, std::tuple > { + // By default, Nets are limited to GMat argument types only + // for infer2, every GMat argument may translate to either + // GArray or GArray. GArray<> part is stripped + // already at this point. + static constexpr const auto value = + std::is_same::type, cv::GMat>::value + || std::is_same::type, cv::Rect>::value; +}; + +// Terminal case 2 (100% failure) +template +struct valid_infer2_types< std::tuple<>, std::tuple > + : public std::false_type { +}; + +// Terminal case 3 (100% failure) +template +struct valid_infer2_types< std::tuple, std::tuple<> > + : public std::false_type { +}; + +// Recursion -- generic +template +struct valid_infer2_types< std::tuple, std::tuple > { + static constexpr const auto value = + valid_infer2_types< std::tuple, std::tuple >::value + && valid_infer2_types< std::tuple, std::tuple >::value; +}; + +// Struct stores network input/output names. +// Used by infer +struct InOutInfo +{ + std::vector in_names; + std::vector out_names; +}; + +template +class GInferOutputsTyped +{ +public: + GInferOutputsTyped() = default; + GInferOutputsTyped(std::shared_ptr call) + : m_priv(std::make_shared(std::move(call))) + { + } + + OutT at(const std::string& name) + { + auto it = m_priv->blobs.find(name); + if (it == m_priv->blobs.end()) { + // FIXME: Avoid modifying GKernel + auto shape = cv::detail::GTypeTraits::shape; + auto kind = cv::detail::GTypeTraits::op_kind; + m_priv->call->kernel().outShapes.push_back(shape); + m_priv->call->kernel().outCtors.emplace_back(cv::detail::GObtainCtor::get()); + m_priv->call->kernel().outKinds.emplace_back(kind); + auto out_idx = static_cast(m_priv->blobs.size()); + it = m_priv->blobs.emplace(name, + cv::detail::Yield::yield(*(m_priv->call), out_idx)).first; + m_priv->info->out_names.push_back(name); + } + return it->second; + } +private: + struct Priv + { + Priv(std::shared_ptr c) + : call(std::move(c)), info(cv::util::any_cast(&call->params())) + { + } + + std::shared_ptr call; + InOutInfo* info = nullptr; + std::unordered_map blobs; + }; + + std::shared_ptr m_priv; +}; + +template +class GInferInputsTyped +{ +public: + GInferInputsTyped() + : m_priv(std::make_shared()) + { + } + + template + GInferInputsTyped& setInput(const std::string& name, U in) + { + m_priv->blobs.emplace(std::piecewise_construct, + std::forward_as_tuple(name), + std::forward_as_tuple(in)); + return *this; + } + + using StorageT = cv::util::variant; + StorageT& operator[](const std::string& name) { + return m_priv->blobs[name]; + } + + using Map = std::unordered_map; + const Map& getBlobs() const { + return m_priv->blobs; + } + +private: + struct Priv + { + std::unordered_map blobs; + }; + + std::shared_ptr m_priv; +}; + +template +std::shared_ptr makeCall(const std::string &tag, + std::vector &&args, + std::vector &&names, + cv::GKinds &&kinds) { + auto call = std::make_shared(GKernel{ + InferT::id(), + tag, + InferT::getOutMeta, + {}, // outShape will be filled later + std::move(kinds), + {}, // outCtors will be filled later + {}, // outKinds will be filled later + }); + + call->setArgs(std::move(args)); + call->params() = cv::detail::InOutInfo{std::move(names), {}}; + + return call; +} + +} // namespace detail + +// TODO: maybe tuple_wrap_helper from util.hpp may help with this. +// Multiple-return-value network definition (specialized base class) +template +class GNetworkType(Args...)> > +{ +public: + using InArgs = std::tuple; + using OutArgs = std::tuple; + + using Result = OutArgs; + using API = std::function; + + using ResultL = std::tuple< cv::GArray... >; +}; + +// Single-return-value network definition (specialized base class) +template +class GNetworkType > +{ +public: + using InArgs = std::tuple; + using OutArgs = std::tuple; + + using Result = R; + using API = std::function; + + using ResultL = cv::GArray; +}; + +// InferAPI: Accepts either GMat or GFrame for very individual network's input +template +struct InferAPI { + using type = typename std::enable_if + < detail::valid_infer_types::value + && std::tuple_size::value == sizeof...(Ts) + , std::function + >::type; +}; + +// InferAPIRoi: Accepts a rectangle and either GMat or GFrame +template +struct InferAPIRoi { + using type = typename std::enable_if + < detail::valid_infer_types::value + && std::tuple_size::value == 1u + , std::function, T)> + >::type; +}; + +// InferAPIList: Accepts a list of rectangles and list of GMat/GFrames; +// crops every input. +template +struct InferAPIList { + using type = typename std::enable_if + < detail::valid_infer_types::value + && std::tuple_size::value == sizeof...(Ts) + , std::function, Ts...)> + >::type; +}; + +// APIList2 is also template to allow different calling options +// (GArray vs GArray per input) +template +struct InferAPIList2 { + using type = typename std::enable_if + < detail::valid_infer_types::value && + cv::detail::valid_infer2_types< typename Net::InArgs + , std::tuple >::value, + std::function...)> + >::type; +}; + +// Base "Infer" kernel. Note - for whatever network, kernel ID +// is always the same. Different inference calls are distinguished by +// network _tag_ (an extra field in GCall) +// +// getOutMeta is a stub callback collected by G-API kernel subsystem +// automatically. This is a rare case when this callback is defined by +// a particular backend, not by a network itself. +struct GInferBase { + static constexpr const char * id() { + return "org.opencv.dnn.infer"; // Universal stub + } + static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) { + return GMetaArgs{}; // One more universal stub + } +}; + +// Base "InferROI" kernel. +// All notes from "Infer" kernel apply here as well. +struct GInferROIBase { + static constexpr const char * id() { + return "org.opencv.dnn.infer-roi"; // Universal stub + } + static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) { + return GMetaArgs{}; // One more universal stub + } +}; + +// Base "Infer list" kernel. +// All notes from "Infer" kernel apply here as well. +struct GInferListBase { + static constexpr const char * id() { + return "org.opencv.dnn.infer-roi-list-1"; // Universal stub + } + static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) { + return GMetaArgs{}; // One more universal stub + } +}; + +// Base "Infer list 2" kernel. +// All notes from "Infer" kernel apply here as well. +struct GInferList2Base { + static constexpr const char * id() { + return "org.opencv.dnn.infer-roi-list-2"; // Universal stub + } + static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) { + return GMetaArgs{}; // One more universal stub + } +}; + +// A generic inference kernel. API (::on()) is fully defined by the Net +// template parameter. +// Acts as a regular kernel in graph (via KernelTypeMedium). +template +struct GInfer final + : public GInferBase + , public detail::KernelTypeMedium< GInfer + , typename InferAPI::type > { + using GInferBase::getOutMeta; // FIXME: name lookup conflict workaround? + + static constexpr const char* tag() { return Net::tag(); } +}; + +// A specific roi-inference kernel. API (::on()) is fixed here and +// verified against Net. +template +struct GInferROI final + : public GInferROIBase + , public detail::KernelTypeMedium< GInferROI + , typename InferAPIRoi::type > { + using GInferROIBase::getOutMeta; // FIXME: name lookup conflict workaround? + + static constexpr const char* tag() { return Net::tag(); } +}; + + +// A generic roi-list inference kernel. API (::on()) is derived from +// the Net template parameter (see more in infer<> overload). +template +struct GInferList final + : public GInferListBase + , public detail::KernelTypeMedium< GInferList + , typename InferAPIList::type > { + using GInferListBase::getOutMeta; // FIXME: name lookup conflict workaround? + + static constexpr const char* tag() { return Net::tag(); } +}; + +// An even more generic roi-list inference kernel. API (::on()) is +// derived from the Net template parameter (see more in infer<> +// overload). +// Takes an extra variadic template list to reflect how this network +// was called (with Rects or GMats as array parameters) +template +struct GInferList2 final + : public GInferList2Base + , public detail::KernelTypeMedium< GInferList2 + , typename InferAPIList2::type > { + using GInferList2Base::getOutMeta; // FIXME: name lookup conflict workaround? + + static constexpr const char* tag() { return Net::tag(); } +}; + +/** + * @brief G-API object used to collect network inputs + */ +using GInferInputs = cv::detail::GInferInputsTyped; + +/** + * @brief G-API object used to collect the list of network inputs + */ +using GInferListInputs = cv::detail::GInferInputsTyped, cv::GArray>; + +/** + * @brief G-API object used to collect network outputs + */ +using GInferOutputs = cv::detail::GInferOutputsTyped; + +/** + * @brief G-API object used to collect the list of network outputs + */ +using GInferListOutputs = cv::detail::GInferOutputsTyped>; + +namespace detail { +void inline unpackBlobs(const cv::GInferInputs::Map& blobs, + std::vector& args, + std::vector& names, + cv::GKinds& kinds) +{ + for (auto&& p : blobs) { + names.emplace_back(p.first); + switch (p.second.index()) { + case cv::GInferInputs::StorageT::index_of(): + args.emplace_back(cv::util::get(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT); + break; + case cv::GInferInputs::StorageT::index_of(): + args.emplace_back(cv::util::get(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_UNKNOWN); + break; + default: + GAPI_Error("InternalError"); + } + } +} + +template +struct InferROITraits; + +template <> +struct InferROITraits +{ + using outType = cv::GInferOutputs; + using inType = cv::GOpaque; +}; + +template <> +struct InferROITraits +{ + using outType = cv::GInferListOutputs; + using inType = cv::GArray; +}; + +template +typename InferROITraits::outType +inferGenericROI(const std::string& tag, + const typename InferROITraits::inType& in, + const cv::GInferInputs& inputs) +{ + std::vector args; + std::vector names; + cv::GKinds kinds; + + args.emplace_back(in); + kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT); + + unpackBlobs(inputs.getBlobs(), args, names, kinds); + + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); + + return {std::move(call)}; +} + +} // namespace detail +} // namespace cv + +// FIXME: Probably the signature makes a function/tuple/function round-trip +#define G_API_NET(Class, API, Tag) \ + struct Class final: public cv::GNetworkType { \ + static constexpr const char * tag() { return Tag; } \ + } + +namespace cv { +namespace gapi { + +/** @brief Calculates response for the specified network (template + * parameter) for the specified region in the source image. + * Currently expects a single-input network only. + * + * @tparam A network type defined with G_API_NET() macro. + * @param in input image where to take ROI from. + * @param roi an object describing the region of interest + * in the source image. May be calculated in the same graph dynamically. + * @return an object of return type as defined in G_API_NET(). + * If a network has multiple return values (defined with a tuple), a tuple of + * objects of appropriate type is returned. + * @sa G_API_NET() + */ +template +typename Net::Result infer(cv::GOpaque roi, T in) { + return GInferROI::on(roi, in); +} + +/** @brief Calculates responses for the specified network (template + * parameter) for every region in the source image. + * + * @tparam A network type defined with G_API_NET() macro. + * @param roi a list of rectangles describing regions of interest + * in the source image. Usually an output of object detector or tracker. + * @param args network's input parameters as specified in G_API_NET() macro. + * NOTE: verified to work reliably with 1-input topologies only. + * @return a list of objects of return type as defined in G_API_NET(). + * If a network has multiple return values (defined with a tuple), a tuple of + * GArray<> objects is returned with the appropriate types inside. + * @sa G_API_NET() + */ +template +typename Net::ResultL infer(cv::GArray roi, Args&&... args) { + return GInferList::on(roi, std::forward(args)...); +} + +/** @brief Calculates responses for the specified network (template + * parameter) for every region in the source image, extended version. + * + * @tparam A network type defined with G_API_NET() macro. + * @param image A source image containing regions of interest + * @param args GArray<> objects of cv::Rect or cv::GMat, one per every + * network input: + * - If a cv::GArray is passed, the appropriate + * regions are taken from `image` and preprocessed to this particular + * network input; + * - If a cv::GArray is passed, the underlying data traited + * as tensor (no automatic preprocessing happen). + * @return a list of objects of return type as defined in G_API_NET(). + * If a network has multiple return values (defined with a tuple), a tuple of + * GArray<> objects is returned with the appropriate types inside. + * @sa G_API_NET() + */ + +template +typename Net::ResultL infer2(T image, cv::GArray... args) { + // FIXME: Declared as "2" because in the current form it steals + // overloads from the regular infer + return GInferList2::on(image, args...); +} + +/** + * @brief Calculates response for the specified network (template + * parameter) given the input data. + * + * @tparam A network type defined with G_API_NET() macro. + * @param args network's input parameters as specified in G_API_NET() macro. + * @return an object of return type as defined in G_API_NET(). + * If a network has multiple return values (defined with a tuple), a tuple of + * objects of appropriate type is returned. + * @sa G_API_NET() + */ +template +typename Net::Result infer(Args&&... args) { + return GInfer::on(std::forward(args)...); +} + +/** + * @brief Generic network type: input and output layers are configured dynamically at runtime + * + * Unlike the network types defined with G_API_NET macro, this one + * doesn't fix number of network inputs and outputs at the compilation stage + * thus providing user with an opportunity to program them in runtime. + */ +struct Generic { }; + +/** + * @brief Calculates response for generic network + * + * @param tag a network tag + * @param inputs networks's inputs + * @return a GInferOutputs + */ +template cv::GInferOutputs +infer(const std::string& tag, const cv::GInferInputs& inputs) +{ + std::vector args; + std::vector names; + cv::GKinds kinds; + + cv::detail::unpackBlobs(inputs.getBlobs(), args, names, kinds); + + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); + + return cv::GInferOutputs{std::move(call)}; +} + +/** @brief Calculates response for the generic network + * for the specified region in the source image. + * Currently expects a single-input network only. + * + * @param tag a network tag + * @param roi a an object describing the region of interest + * in the source image. May be calculated in the same graph dynamically. + * @param inputs networks's inputs + * @return a cv::GInferOutputs + */ +template cv::GInferOutputs +infer(const std::string& tag, const cv::GOpaque& roi, const cv::GInferInputs& inputs) +{ + return cv::detail::inferGenericROI(tag, roi, inputs); +} + +/** @brief Calculates responses for the specified network + * for every region in the source image. + * + * @param tag a network tag + * @param rois a list of rectangles describing regions of interest + * in the source image. Usually an output of object detector or tracker. + * @param inputs networks's inputs + * @return a cv::GInferListOutputs + */ +template cv::GInferListOutputs +infer(const std::string& tag, const cv::GArray& rois, const cv::GInferInputs& inputs) +{ + return cv::detail::inferGenericROI(tag, rois, inputs); +} + +/** @brief Calculates responses for the specified network + * for every region in the source image, extended version. + * + * @param tag a network tag + * @param in a source image containing regions of interest. + * @param inputs networks's inputs + * @return a cv::GInferListOutputs + */ +template +typename std::enable_if::value, cv::GInferListOutputs>::type +infer2(const std::string& tag, + const Input& in, + const cv::GInferListInputs& inputs) +{ + std::vector args; + std::vector names; + cv::GKinds kinds; + + args.emplace_back(in); + auto k = cv::detail::GOpaqueTraits::kind; + kinds.emplace_back(k); + + for (auto&& p : inputs.getBlobs()) { + names.emplace_back(p.first); + switch (p.second.index()) { + case cv::GInferListInputs::StorageT::index_of>(): + args.emplace_back(cv::util::get>(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT); + break; + case cv::GInferListInputs::StorageT::index_of>(): + args.emplace_back(cv::util::get>(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT); + break; + default: + GAPI_Error("InternalError"); + } + } + + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); + + return cv::GInferListOutputs{std::move(call)}; +} + +} // namespace gapi +} // namespace cv + +#endif // GAPI_STANDALONE + +namespace cv { +namespace gapi { + +// Note: the below code _is_ part of STANDALONE build, +// just to make our compiler code compileable. + +// A type-erased form of network parameters. +// Similar to how a type-erased GKernel is represented and used. +/// @private +struct GAPI_EXPORTS_W_SIMPLE GNetParam { + std::string tag; // FIXME: const? + GBackend backend; // Specifies the execution model + util::any params; // Backend-interpreted parameter structure +}; + +/** \addtogroup gapi_compile_args + * @{ + */ +/** + * @brief A container class for network configurations. Similar to + * GKernelPackage. Use cv::gapi::networks() to construct this object. + * + * @sa cv::gapi::networks + */ +struct GAPI_EXPORTS_W_SIMPLE GNetPackage { + GAPI_WRAP GNetPackage() = default; + GAPI_WRAP explicit GNetPackage(std::vector nets); + explicit GNetPackage(std::initializer_list ii); + std::vector backends() const; + std::vector networks; +}; +/** @} gapi_compile_args */ +} // namespace gapi + +namespace detail { +template +gapi::GNetParam strip(T&& t) { + return gapi::GNetParam { t.tag() + , t.backend() + , t.params() + }; +} + +template<> struct CompileArgTag { + static const char* tag() { return "gapi.net_package"; } +}; + +} // namespace cv::detail + +namespace gapi { +template +cv::gapi::GNetPackage networks(Args&&... args) { + return cv::gapi::GNetPackage({ cv::detail::strip(args)... }); +} + +inline cv::gapi::GNetPackage& operator += ( cv::gapi::GNetPackage& lhs, + const cv::gapi::GNetPackage& rhs) { + lhs.networks.reserve(lhs.networks.size() + rhs.networks.size()); + lhs.networks.insert(lhs.networks.end(), rhs.networks.begin(), rhs.networks.end()); + return lhs; +} + +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ie.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ie.hpp new file mode 100644 index 0000000000000000000000000000000000000000..94272dea55b0db6167f8a1619686efbd6840010c --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ie.hpp @@ -0,0 +1,70 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_INFER_BINDINGS_IE_HPP +#define OPENCV_GAPI_INFER_BINDINGS_IE_HPP + +#include +#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS +#include // GKernelPackage +#include // Params + +#include + +namespace cv { +namespace gapi { +namespace ie { + +// NB: Used by python wrapper +// This class can be marked as SIMPLE, because it's implemented as pimpl +class GAPI_EXPORTS_W_SIMPLE PyParams { +public: + GAPI_WRAP + PyParams() = default; + + GAPI_WRAP + PyParams(const std::string &tag, + const std::string &model, + const std::string &weights, + const std::string &device); + + GAPI_WRAP + PyParams(const std::string &tag, + const std::string &model, + const std::string &device); + + GAPI_WRAP + PyParams& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR); + + GAPI_WRAP + PyParams& cfgNumRequests(size_t nireq); + + GAPI_WRAP + PyParams& cfgBatchSize(const size_t size); + + GBackend backend() const; + std::string tag() const; + cv::util::any params() const; + +private: + std::shared_ptr> m_priv; +}; + +GAPI_EXPORTS_W PyParams params(const std::string &tag, + const std::string &model, + const std::string &weights, + const std::string &device); + +GAPI_EXPORTS_W PyParams params(const std::string &tag, + const std::string &model, + const std::string &device); +} // namespace ie +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_BINDINGS_IE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_onnx.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_onnx.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f7bb2599242d73a8ca593c7a979cf94a55fb70f3 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_onnx.hpp @@ -0,0 +1,74 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level +// directory of this distribution and at http://opencv.org/license.html. + +#ifndef OPENCV_GAPI_INFER_BINDINGS_ONNX_HPP +#define OPENCV_GAPI_INFER_BINDINGS_ONNX_HPP + +#include // GKernelPackage +#include // Params +#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS +#include + +#include + +namespace cv { +namespace gapi { +namespace onnx { + +// NB: Used by python wrapper +// This class can be marked as SIMPLE, because it's implemented as pimpl +class GAPI_EXPORTS_W_SIMPLE PyParams { +public: + GAPI_WRAP + PyParams() = default; + + GAPI_WRAP + PyParams(const std::string& tag, const std::string& model_path); + + GAPI_WRAP + PyParams& cfgMeanStd(const std::string &layer_name, + const cv::Scalar &m, + const cv::Scalar &s); + GAPI_WRAP + PyParams& cfgNormalize(const std::string &layer_name, bool flag); + + GAPI_WRAP + PyParams& cfgAddExecutionProvider(ep::OpenVINO ep); + + GAPI_WRAP + PyParams& cfgAddExecutionProvider(ep::DirectML ep); + + GAPI_WRAP + PyParams& cfgAddExecutionProvider(ep::CoreML ep); + + GAPI_WRAP + PyParams& cfgAddExecutionProvider(ep::CUDA ep); + + GAPI_WRAP + PyParams& cfgAddExecutionProvider(ep::TensorRT ep); + + GAPI_WRAP + PyParams& cfgDisableMemPattern(); + + GAPI_WRAP + PyParams& cfgSessionOptions(const std::map& options); + + GAPI_WRAP + PyParams& cfgOptLevel(const int opt_level); + + GBackend backend() const; + std::string tag() const; + cv::util::any params() const; + +private: + std::shared_ptr> m_priv; +}; + +GAPI_EXPORTS_W PyParams params(const std::string& tag, const std::string& model_path); + +} // namespace onnx +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_BINDINGS_ONNX_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ov.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ov.hpp new file mode 100644 index 0000000000000000000000000000000000000000..08f5c83a3ff42825c8901fe3983747d6675ea86c --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/bindings_ov.hpp @@ -0,0 +1,128 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2023 Intel Corporation + +#ifndef OPENCV_GAPI_INFER_BINDINGS_OV_HPP +#define OPENCV_GAPI_INFER_BINDINGS_OV_HPP + +#include +#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS +#include // GKernelPackage +#include // Params + +#include + +namespace cv { +namespace gapi { +namespace ov { + +// NB: Used by python wrapper +// This class can be marked as SIMPLE, because it's implemented as pimpl +class GAPI_EXPORTS_W_SIMPLE PyParams { +public: + GAPI_WRAP + PyParams() = default; + + GAPI_WRAP + PyParams(const std::string &tag, + const std::string &model_path, + const std::string &bin_path, + const std::string &device); + + GAPI_WRAP + PyParams(const std::string &tag, + const std::string &blob_path, + const std::string &device); + + GAPI_WRAP + PyParams& cfgPluginConfig( + const std::map &config); + + GAPI_WRAP + PyParams& cfgInputTensorLayout(std::string tensor_layout); + + GAPI_WRAP + PyParams& cfgInputTensorLayout( + std::map layout_map); + + GAPI_WRAP + PyParams& cfgInputModelLayout(std::string tensor_layout); + + GAPI_WRAP + PyParams& cfgInputModelLayout( + std::map layout_map); + + GAPI_WRAP + PyParams& cfgOutputTensorLayout(std::string tensor_layout); + + GAPI_WRAP + PyParams& cfgOutputTensorLayout( + std::map layout_map); + + GAPI_WRAP + PyParams& cfgOutputModelLayout(std::string tensor_layout); + + GAPI_WRAP + PyParams& cfgOutputModelLayout( + std::map layout_map); + + GAPI_WRAP + PyParams& cfgOutputTensorPrecision(int precision); + + GAPI_WRAP + PyParams& cfgOutputTensorPrecision( + std::map precision_map); + + GAPI_WRAP + PyParams& cfgReshape(std::vector new_shape); + + GAPI_WRAP + PyParams& cfgReshape( + std::map> new_shape_map); + + GAPI_WRAP + PyParams& cfgNumRequests(const size_t nireq); + + GAPI_WRAP + PyParams& cfgMean(std::vector mean_values); + + GAPI_WRAP + PyParams& cfgMean( + std::map> mean_map); + + GAPI_WRAP + PyParams& cfgScale(std::vector scale_values); + + GAPI_WRAP + PyParams& cfgScale( + std::map> scale_map); + + GAPI_WRAP + PyParams& cfgResize(int interpolation); + + GAPI_WRAP + PyParams& cfgResize(std::map interpolation); + + GBackend backend() const; + std::string tag() const; + cv::util::any params() const; + +private: + std::shared_ptr> m_priv; +}; + +GAPI_EXPORTS_W PyParams params(const std::string &tag, + const std::string &model_path, + const std::string &weights, + const std::string &device); + +GAPI_EXPORTS_W PyParams params(const std::string &tag, + const std::string &bin_path, + const std::string &device); +} // namespace ov +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_BINDINGS_OV_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ie.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ie.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9f9518d0b8e08446b4be1190dbb217d52dabc847 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ie.hpp @@ -0,0 +1,711 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019-2023 Intel Corporation + +#ifndef OPENCV_GAPI_INFER_IE_HPP +#define OPENCV_GAPI_INFER_IE_HPP + +#include +#include +#include +#include +#include // tuple, tuple_size +#include + +#include +#include + +#include // GAPI_EXPORTS +#include // GKernelPackage +#include // Generic +#include // Preproc Dev & Ctx + +namespace cv { +namespace gapi { +// FIXME: introduce a new sub-namespace for NN? + +/** + * @brief This namespace contains G-API OpenVINO backend functions, + * structures, and symbols. + */ +namespace ie { + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +/** + * Specifies how G-API and IE should trait input data + * + * In OpenCV, the same cv::Mat is used to represent both + * image and tensor data. Sometimes those are hardly distinguishable, + * so this extra parameter is used to give G-API a hint. + * + * This hint controls how G-API reinterprets the data when converting + * it to IE Blob format (and which layout/etc is assigned to this data). + */ +enum class TraitAs: int +{ + TENSOR, //!< G-API traits an associated cv::Mat as a raw tensor and passes dimensions as-is + IMAGE //!< G-API traits an associated cv::Mat as an image so creates an "image" blob (NCHW/NHWC, etc) +}; + +using IEConfig = std::map; + +enum InferMode {Sync, Async}; + +namespace detail { + +template +using AttrMap = std::map; +// NB: This type is used to hold in/out layers +// attributes such as precision, layout, shape etc. +// +// User can provide attributes either: +// 1. cv::util::monostate - No value specified explicitly. +// 2. Attr - value specified explicitly that should be broadcasted to all layers. +// 3. AttrMap[str->T] - map specifies value for particular layer. +template +using LayerVariantAttr = cv::util::variant< cv::util::monostate + , AttrMap + , Attr>; + +struct ParamDesc { + std::string model_path; + std::string weights_path; + std::string device_id; + + std::vector input_names; + std::vector output_names; + + using ConstInput = std::pair; + std::unordered_map const_inputs; + + std::size_t num_in; + std::size_t num_out; + + enum class Kind {Load, Import}; + Kind kind; + bool is_generic; + IEConfig config; + + std::map> reshape_table; + std::unordered_set layer_names_to_reshape; + + // NB: Number of asyncrhonious infer requests + size_t nireq; + + // NB: An optional config to setup RemoteContext for IE + cv::util::any context_config; + + // NB: batch_size can't be equal to 1 by default, because some of models + // have 2D (Layout::NC) input and if the first dimension not equal to 1 + // net.setBatchSize(1) will overwrite it. + cv::optional batch_size; + + cv::optional vpl_preproc_device; + cv::optional vpl_preproc_ctx; + + InferMode mode; + + using PrecisionT = int; + using PrecisionMapT = std::unordered_map; + // NB: This parameter can contain: + // 1. cv::util::monostate - Don't specify precision, but use default from IR/Blob. + // 2. PrecisionT (CV_8U, CV_32F, ...) - Specifies precision for all output layers. + // 3. PrecisionMapT ({{"layer0", CV_32F}, {"layer1", CV_16F}} - Specifies precision for certain output layer. + // cv::util::monostate is default value that means precision wasn't specified. + using PrecisionVariantT = cv::util::variant; + + PrecisionVariantT output_precision; + LayerVariantAttr input_layout; + LayerVariantAttr output_layout; + LayerVariantAttr interpolation; +}; +} // namespace detail + +// FIXME: this is probably a shared (reusable) thing +template +struct PortCfg { + using In = std::array + < std::string + , std::tuple_size::value >; + using Out = std::array + < std::string + , std::tuple_size::value >; +}; + +/** + * @brief This structure provides functions + * that fill inference parameters for "OpenVINO Toolkit" model. + */ +template class Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and specifies default values for other + inference description parameters. Model is loaded and compiled using "OpenVINO Toolkit". + + @param model Path to topology IR (.xml file). + @param weights Path to weights (.bin file). + @param device target device to use. + */ + Params(const std::string &model, + const std::string &weights, + const std::string &device) + : desc{ model, weights, device, {}, {}, {} + , std::tuple_size::value // num_in + , std::tuple_size::value // num_out + , detail::ParamDesc::Kind::Load + , false + , {} + , {} + , {} + , 1u + , {} + , {} + , {} + , {} + , InferMode::Async + , {} + , {} + , {} + , {} } { + } + + /** @overload + Use this constructor to work with pre-compiled network. + Model is imported from a pre-compiled blob. + + @param model Path to model. + @param device target device to use. + */ + Params(const std::string &model, + const std::string &device) + : desc{ model, {}, device, {}, {}, {} + , std::tuple_size::value // num_in + , std::tuple_size::value // num_out + , detail::ParamDesc::Kind::Import + , false + , {} + , {} + , {} + , 1u + , {} + , {} + , {} + , {} + , InferMode::Async + , {} + , {} + , {} + , {} } { + } + + /** @brief Specifies sequence of network input layers names for inference. + + The function is used to associate cv::gapi::infer<> inputs with the model inputs. + Number of names has to match the number of network inputs as defined in G_API_NET(). + In case a network has only single input layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains names of input layers. + @return reference to this parameter structure. + */ + Params& cfgInputLayers(const typename PortCfg::In &layer_names) { + desc.input_names.clear(); + desc.input_names.reserve(layer_names.size()); + std::copy(layer_names.begin(), layer_names.end(), + std::back_inserter(desc.input_names)); + return *this; + } + + /** @brief Specifies sequence of network output layers names for inference. + + The function is used to associate cv::gapi::infer<> outputs with the model outputs. + Number of names has to match the number of network outputs as defined in G_API_NET(). + In case a network has only single output layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of outputs + as defined in the @ref G_API_NET. Contains names of output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputLayers(const typename PortCfg::Out &layer_names) { + desc.output_names.clear(); + desc.output_names.reserve(layer_names.size()); + std::copy(layer_names.begin(), layer_names.end(), + std::back_inserter(desc.output_names)); + return *this; + } + + /** @brief Specifies a constant input. + + The function is used to set a constant input. This input has to be + a preprocessed tensor if its type is TENSOR. Need to provide name of the + network layer which will receive provided data. + + @param layer_name Name of network layer. + @param data cv::Mat that contains data which will be associated with network layer. + @param hint Input type @sa cv::gapi::ie::TraitAs. + @return reference to this parameter structure. + */ + Params& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR) { + desc.const_inputs[layer_name] = {data, hint}; + return *this; + } + + /** @brief Specifies OpenVINO plugin configuration. + + The function is used to set configuration for OpenVINO plugin. Some parameters + can be different for each plugin. Please follow https://docs.openvinotoolkit.org/latest/index.html + to check information about specific plugin. + + @param cfg Map of pairs: (config parameter name, config parameter value). + @return reference to this parameter structure. + */ + Params& pluginConfig(const IEConfig& cfg) { + desc.config = cfg; + return *this; + } + + /** @overload + Function with a rvalue parameter. + + @param cfg rvalue map of pairs: (config parameter name, config parameter value). + @return reference to this parameter structure. + */ + Params& pluginConfig(IEConfig&& cfg) { + desc.config = std::move(cfg); + return *this; + } + + /** @brief Specifies configuration for RemoteContext in InferenceEngine. + + When RemoteContext is configured the backend imports the networks using the context. + It also expects cv::MediaFrames to be actually remote, to operate with blobs via the context. + + @param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap. + @return reference to this parameter structure. + */ + Params& cfgContextParams(const cv::util::any& ctx_cfg) { + desc.context_config = ctx_cfg; + return *this; + } + + /** @overload + Function with an rvalue parameter. + + @param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap. + @return reference to this parameter structure. + */ + Params& cfgContextParams(cv::util::any&& ctx_cfg) { + desc.context_config = std::move(ctx_cfg); + return *this; + } + + /** @brief Specifies number of asynchronous inference requests. + + @param nireq Number of inference asynchronous requests. + @return reference to this parameter structure. + */ + Params& cfgNumRequests(size_t nireq) { + GAPI_Assert(nireq > 0 && "Number of infer requests must be greater than zero!"); + desc.nireq = nireq; + return *this; + } + + /** @brief Specifies new input shapes for the network inputs. + + The function is used to specify new input shapes for the network inputs. + Follow https://docs.openvinotoolkit.org/latest/classInferenceEngine_1_1networkNetwork.html + for additional information. + + @param reshape_table Map of pairs: name of corresponding data and its dimension. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::map>& reshape_table) { + desc.reshape_table = reshape_table; + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::map>&& reshape_table) { + desc.reshape_table = std::move(reshape_table); + return *this; + } + + /** @overload + + @param layer_name Name of layer. + @param layer_dims New dimensions for this layer. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::string& layer_name, const std::vector& layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::string&& layer_name, std::vector&& layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload + + @param layer_names set of names of network layers that will be used for network reshape. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::unordered_set& layer_names) { + desc.layer_names_to_reshape = layer_names; + return *this; + } + + /** @overload + + @param layer_names rvalue set of the selected layers will be reshaped automatically + its input image size. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(std::unordered_set&& layer_names) { + desc.layer_names_to_reshape = std::move(layer_names); + return *this; + } + + /** @brief Specifies the inference batch size. + + The function is used to specify inference batch size. + Follow https://docs.openvinotoolkit.org/latest/classInferenceEngine_1_1CNNNetwork.html#a8e9d19270a48aab50cb5b1c43eecb8e9 for additional information + + @param size batch size which will be used. + @return reference to this parameter structure. + */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = cv::util::make_optional(size); + return *this; + } + + Params& cfgPreprocessingParams(const cv::gapi::wip::onevpl::Device &device, + const cv::gapi::wip::onevpl::Context &ctx) { + desc.vpl_preproc_device = cv::util::make_optional(device); + desc.vpl_preproc_ctx = cv::util::make_optional(ctx); + return *this; + } + + /** @brief Specifies which api will be used to run inference. + + The function is used to specify mode for OpenVINO inference. + OpenVINO has two options to run inference: + 1. Asynchronous (using StartAsync: https://docs.openvino.ai/latest/classInferenceEngine_1_1InferRequest.html#doxid-class-inference-engine-1-1-infer-request-1a405293e8423d82a5b45f642a3bef0d24) + 2. Synchronous (using Infer: https://docs.openvino.ai/latest/classInferenceEngine_1_1InferRequest.html#doxid-class-inference-engine-1-1-infer-request-1a3391ce30894abde730523e9ca9371ce8) + By default asynchronous mode is used. + + @param mode Inference mode which will be used. + @return reference to this parameter structure. + */ + Params& cfgInferMode(InferMode mode) { + desc.mode = mode; + return *this; + } + + /** @brief Specifies the output precision for model. + + The function is used to set an output precision for model. + + @param precision Precision in OpenCV format (CV_8U, CV_32F, ...) + will be applied to all output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputPrecision(detail::ParamDesc::PrecisionT precision) { + desc.output_precision = precision; + return *this; + } + + /** @overload + + @param precision_map Map of pairs: name of corresponding output layer + and its precision in OpenCV format (CV_8U, CV_32F, ...) + @return reference to this parameter structure. + */ + Params& + cfgOutputPrecision(detail::ParamDesc::PrecisionMapT precision_map) { + desc.output_precision = precision_map; + return *this; + } + + /** @brief Specifies the input layout for model. + + The function is used to set an input layout for model. + + @param layout Layout in string representation ("NCHW", "NHWC", etc) + will be applied to all input layers. + @return reference to this parameter structure. + */ + Params& cfgInputLayout(std::string layout) { + desc.input_layout = std::move(layout); + return *this; + } + + /** @overload + + @param layout_map Map of pairs: name of corresponding input layer + and its layout in string representation ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgInputLayout(detail::AttrMap layout_map) { + desc.input_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies the output layout for model. + + The function is used to set an output layout for model. + + @param layout Layout in string representation ("NCHW", "NHWC", etc) + will be applied to all output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputLayout(std::string layout) { + desc.output_layout = std::move(layout); + return *this; + } + + /** @overload + + @param layout_map Map of pairs: name of corresponding output layer + and its layout in string representation ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgOutputLayout(detail::AttrMap layout_map) { + desc.output_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies resize interpolation algorithm. + * + The function is used to configure resize preprocessing for input layer. + + @param interpolation Resize interpolation algorithm. + Supported algorithms: #INTER_LINEAR, #INTER_AREA. + @return reference to this parameter structure. + */ + Params& cfgResize(int interpolation) { + desc.interpolation = interpolation; + return *this; + } + + /** @overload + + @param interpolation Map of pairs: name of corresponding input layer + and its resize algorithm. + @return reference to this parameter structure. + */ + Params& cfgResize(detail::AttrMap interpolation) { + desc.interpolation = std::move(interpolation); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::ie::backend(); } + std::string tag() const { return Net::tag(); } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) + +protected: + detail::ParamDesc desc; +}; + +/* +* @brief This structure provides functions for generic network type that +* fill inference parameters. +* @see struct Generic +*/ +template<> +class Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and sets default values for other + inference description parameters. Model is loaded and compiled using OpenVINO Toolkit. + + @param tag string tag of the network for which these parameters are intended. + @param model path to topology IR (.xml file). + @param weights path to weights (.bin file). + @param device target device to use. + */ + Params(const std::string &tag, + const std::string &model, + const std::string &weights, + const std::string &device) + : desc{ model, weights, device, {}, {}, {}, 0u, 0u, + detail::ParamDesc::Kind::Load, true, {}, {}, {}, 1u, + {}, {}, {}, {}, InferMode::Async, {}, {}, {}, {} }, + m_tag(tag) { + } + + /** @overload + + This constructor for pre-compiled networks. Model is imported from pre-compiled + blob. + + @param tag string tag of the network for which these parameters are intended. + @param model path to model. + @param device target device to use. + */ + Params(const std::string &tag, + const std::string &model, + const std::string &device) + : desc{ model, {}, device, {}, {}, {}, 0u, 0u, + detail::ParamDesc::Kind::Import, true, {}, {}, {}, 1u, + {}, {}, {}, {}, InferMode::Async, {}, {}, {}, {} }, + m_tag(tag) { + } + + /** @see ie::Params::pluginConfig. */ + Params& pluginConfig(const IEConfig& cfg) { + desc.config = cfg; + return *this; + } + + /** @overload */ + Params& pluginConfig(IEConfig&& cfg) { + desc.config = std::move(cfg); + return *this; + } + + /** @see ie::Params::constInput. */ + Params& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR) { + desc.const_inputs[layer_name] = {data, hint}; + return *this; + } + + /** @see ie::Params::cfgNumRequests. */ + Params& cfgNumRequests(size_t nireq) { + GAPI_Assert(nireq > 0 && "Number of infer requests must be greater than zero!"); + desc.nireq = nireq; + return *this; + } + + /** @see ie::Params::cfgInputReshape */ + Params& cfgInputReshape(const std::map>&reshape_table) { + desc.reshape_table = reshape_table; + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::map> && reshape_table) { + desc.reshape_table = std::move(reshape_table); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::string && layer_name, std::vector && layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(const std::string & layer_name, const std::vector&layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::unordered_set && layer_names) { + desc.layer_names_to_reshape = std::move(layer_names); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(const std::unordered_set&layer_names) { + desc.layer_names_to_reshape = layer_names; + return *this; + } + + /** @see ie::Params::cfgBatchSize */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = cv::util::make_optional(size); + return *this; + } + + /** @see ie::Params::cfgInferAPI */ + Params& cfgInferMode(InferMode mode) { + desc.mode = mode; + return *this; + } + + /** @see ie::Params::cfgOutputPrecision */ + Params& cfgOutputPrecision(detail::ParamDesc::PrecisionT precision) { + desc.output_precision = precision; + return *this; + } + + /** @overload */ + Params& + cfgOutputPrecision(detail::ParamDesc::PrecisionMapT precision_map) { + desc.output_precision = precision_map; + return *this; + } + + /** @see ie::Params::cfgInputLayout */ + Params& cfgInputLayout(std::string layout) { + desc.input_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgInputLayout(detail::AttrMap layout_map) { + desc.input_layout = std::move(layout_map); + return *this; + } + + /** @see ie::Params::cfgOutputLayout */ + Params& cfgOutputLayout(std::string layout) { + desc.output_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgOutputLayout(detail::AttrMap layout_map) { + desc.output_layout = std::move(layout_map); + return *this; + } + + /** @see ie::Params::cfgResize */ + Params& cfgResize(int interpolation) { + desc.interpolation = interpolation; + return *this; + } + + /** @overload */ + Params& cfgResize(detail::AttrMap interpolation) { + desc.interpolation = std::move(interpolation); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::ie::backend(); } + std::string tag() const { return m_tag; } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) + +protected: + detail::ParamDesc desc; + std::string m_tag; +}; + +} // namespace ie +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_IE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/onnx.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/onnx.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eb6316b446818614cfc1eb9b976a812cfdf4a4e5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/onnx.hpp @@ -0,0 +1,759 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020-2021 Intel Corporation + +#ifndef OPENCV_GAPI_INFER_ONNX_HPP +#define OPENCV_GAPI_INFER_ONNX_HPP + +#include +#include +#include +#include // tuple, tuple_size +#include + +#include +#include +#include + +#include // GAPI_EXPORTS +#include // GKernelPackage +#include // Generic + +namespace cv { +namespace gapi { + +/** + * @brief This namespace contains G-API ONNX Runtime backend functions, structures, and symbols. + */ +namespace onnx { + +/** + * @brief This namespace contains Execution Providers structures for G-API ONNX Runtime backend. + */ +namespace ep { + +/** + * @brief This structure provides functions + * that fill inference options for ONNX CoreML Execution Provider. + * Please follow https://onnxruntime.ai/docs/execution-providers/CoreML-ExecutionProvider.html#coreml-execution-provider + */ +struct GAPI_EXPORTS_W_SIMPLE CoreML { + /** @brief Class constructor. + + Constructs CoreML parameters. + + */ + GAPI_WRAP + CoreML() = default; + + /** @brief Limit CoreML Execution Provider to run on CPU only. + + This function is used to limit CoreML to run on CPU only. + Please follow: https://onnxruntime.ai/docs/execution-providers/CoreML-ExecutionProvider.html#coreml_flag_use_cpu_only + + @return reference to this parameter structure. + */ + GAPI_WRAP + CoreML& cfgUseCPUOnly() { + use_cpu_only = true; + return *this; + } + + /** @brief Enable CoreML EP to run on a subgraph in the body of a control flow ONNX operator (i.e. a Loop, Scan or If operator). + + This function is used to enable CoreML EP to run on + a subgraph of a control flow of ONNX operation. + Please follow: https://onnxruntime.ai/docs/execution-providers/CoreML-ExecutionProvider.html#coreml_flag_enable_on_subgraph + + @return reference to this parameter structure. + */ + GAPI_WRAP + CoreML& cfgEnableOnSubgraph() { + enable_on_subgraph = true; + return *this; + } + + /** @brief Enable CoreML EP to run only on Apple Neural Engine. + + This function is used to enable CoreML EP to run only on Apple Neural Engine. + Please follow: https://onnxruntime.ai/docs/execution-providers/CoreML-ExecutionProvider.html#coreml_flag_only_enable_device_with_ane + + @return reference to this parameter structure. + */ + GAPI_WRAP + CoreML& cfgEnableOnlyNeuralEngine() { + enable_only_ane = true; + return *this; + } + + bool use_cpu_only = false; + bool enable_on_subgraph = false; + bool enable_only_ane = false; +}; + +/** + * @brief This structure provides functions + * that fill inference options for CUDA Execution Provider. + * Please follow https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#cuda-execution-provider + */ +struct GAPI_EXPORTS_W_SIMPLE CUDA { + // NB: Used from python. + /// @private -- Exclude this constructor from OpenCV documentation + GAPI_WRAP + CUDA() = default; + + /** @brief Class constructor. + + Constructs CUDA parameters based on device type information. + + @param dev_id Target device id to use. + */ + GAPI_WRAP + explicit CUDA(const int dev_id) + : device_id(dev_id) { + } + + int device_id; +}; + +/** + * @brief This structure provides functions + * that fill inference options for TensorRT Execution Provider. + * Please follow https://onnxruntime.ai/docs/execution-providers/TensorRT-ExecutionProvider.html#tensorrt-execution-provider + */ +struct GAPI_EXPORTS_W_SIMPLE TensorRT { + // NB: Used from python. + /// @private -- Exclude this constructor from OpenCV documentation + GAPI_WRAP + TensorRT() = default; + + /** @brief Class constructor. + + Constructs TensorRT parameters based on device type information. + + @param dev_id Target device id to use. + */ + GAPI_WRAP + explicit TensorRT(const int dev_id) + : device_id(dev_id) { + } + + int device_id; +}; + +/** + * @brief This structure provides functions + * that fill inference options for ONNX OpenVINO Execution Provider. + * Please follow https://onnxruntime.ai/docs/execution-providers/OpenVINO-ExecutionProvider.html#summary-of-options + */ +struct GAPI_EXPORTS_W_SIMPLE OpenVINO { + // NB: Used from python. + /// @private -- Exclude this constructor from OpenCV documentation + GAPI_WRAP + OpenVINO() = default; + + /** @brief Class constructor. + + Constructs OpenVINO parameters based on device type information. + + @param dev_type Target device type to use. ("CPU", "GPU", "GPU.0" etc) + */ + GAPI_WRAP + explicit OpenVINO(const std::string &dev_type) + : device_type(dev_type) { + } + + /** @brief Class constructor. + + Constructs OpenVINO parameters based on map of options passed. + + * @param params A map of parameter names and their corresponding string values. + */ + GAPI_WRAP + explicit OpenVINO(const std::map& params) + : params_map(params) { + } + + /** @brief Specifies OpenVINO Execution Provider cache dir. + + This function is used to explicitly specify the path to save and load + the blobs enabling model caching feature. + + @param dir Path to the directory what will be used as cache. + @return reference to this parameter structure. + */ + GAPI_WRAP + OpenVINO& cfgCacheDir(const std::string &dir) { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } + cache_dir = dir; + return *this; + } + + /** @brief Specifies OpenVINO Execution Provider number of threads. + + This function is used to override the accelerator default value + of number of threads with this value at runtime. + + @param nthreads Number of threads. + @return reference to this parameter structure. + */ + GAPI_WRAP + OpenVINO& cfgNumThreads(size_t nthreads) { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } + num_of_threads = nthreads; + return *this; + } + + /** @brief Enables OpenVINO Execution Provider opencl throttling. + + This function is used to enable OpenCL queue throttling for GPU devices + (reduces CPU utilization when using GPU). + + @return reference to this parameter structure. + */ + GAPI_WRAP + OpenVINO& cfgEnableOpenCLThrottling() { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } + enable_opencl_throttling = true; + return *this; + } + + /** @brief Enables OpenVINO Execution Provider dynamic shapes. + + This function is used to enable OpenCL queue throttling for GPU devices + (reduces CPU utilization when using GPU). + This function is used to enable work with dynamic shaped models + whose shape will be set dynamically based on the infer input + image/data shape at run time in CPU. + + @return reference to this parameter structure. + */ + GAPI_WRAP + OpenVINO& cfgEnableDynamicShapes() { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } + enable_dynamic_shapes = true; + return *this; + } + + std::string device_type; + std::string cache_dir; + size_t num_of_threads = 0; + bool enable_opencl_throttling = false; + bool enable_dynamic_shapes = false; + std::map params_map; +}; + +/** + * @brief This structure provides functions + * that fill inference options for ONNX DirectML Execution Provider. + * Please follow https://onnxruntime.ai/docs/execution-providers/DirectML-ExecutionProvider.html#directml-execution-provider + */ +class GAPI_EXPORTS_W_SIMPLE DirectML { +public: + // NB: Used from python. + /// @private -- Exclude this constructor from OpenCV documentation + GAPI_WRAP + DirectML() = default; + + /** @brief Class constructor. + + Constructs DirectML parameters based on device id. + + @param device_id Target device id to use. ("0", "1", etc) + */ + GAPI_WRAP + explicit DirectML(const int device_id) : ddesc(device_id) { }; + + /** @brief Class constructor. + + Constructs DirectML parameters based on adapter name. + + @param adapter_name Target adapter_name to use. + */ + GAPI_WRAP + explicit DirectML(const std::string &adapter_name) : ddesc(adapter_name) { }; + + using DeviceDesc = cv::util::variant; + DeviceDesc ddesc; +}; + +using EP = cv::util::variant< cv::util::monostate + , OpenVINO + , DirectML + , CoreML + , CUDA + , TensorRT>; + +} // namespace ep + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +enum class TraitAs: int { + TENSOR, //!< G-API traits an associated cv::Mat as a raw tensor + // and passes dimensions as-is + IMAGE //!< G-API traits an associated cv::Mat as an image so + // creates an "image" blob (NCHW/NHWC, etc) +}; + +using PostProc = std::function &, + std::unordered_map &)>; + +namespace detail { +/** +* @brief This structure contains description of inference parameters +* which is specific to ONNX models. +*/ +struct ParamDesc { + std::string model_path; //!< Path to model. + + // NB: nun_* may differ from topology's real input/output port numbers + // (e.g. topology's partial execution) + std::size_t num_in; //!< How many inputs are defined in the operation + std::size_t num_out; //!< How many outputs are defined in the operation + + // NB: Here order follows the `Net` API + std::vector input_names; //!< Names of input network layers. + std::vector output_names; //!< Names of output network layers. + + using ConstInput = std::pair; + std::unordered_map const_inputs; //!< Map with pair of name of network layer and ConstInput which will be associated with this. + + std::vector mean; //!< Mean values for preprocessing. + std::vector stdev; //!< Standard deviation values for preprocessing. + + std::vector out_metas; //!< Out meta information about your output (type, dimension). + PostProc custom_post_proc; //!< Post processing function. + + std::vector normalize; //!< Vector of bool values that enabled or disabled normalize of input data. + + std::vector names_to_remap; //!< Names of output layers that will be processed in PostProc function. + + bool is_generic; + + // TODO: Needs to modify the rest of ParamDesc accordingly to support + // both generic and non-generic options without duplication + // (as it was done for the OV IE backend) + // These values are pushed into the respective vector<> fields above + // when the generic infer parameters are unpacked (see GONNXBackendImpl::unpackKernel) + std::unordered_map > generic_mstd; + std::unordered_map generic_norm; + + std::map session_options; + std::vector execution_providers; + bool disable_mem_pattern; + cv::util::optional opt_level; +}; +} // namespace detail + +template +struct PortCfg { + using In = std::array + < std::string + , std::tuple_size::value >; + using Out = std::array + < std::string + , std::tuple_size::value >; + using NormCoefs = std::array + < cv::Scalar + , std::tuple_size::value >; + using Normalize = std::array + < bool + , std::tuple_size::value >; +}; + +/** + * Contains description of inference parameters and kit of functions that + * fill this parameters. + */ +template class Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and sets default values for other + inference description parameters. + + @param model Path to model (.onnx file). + */ + Params(const std::string &model) { + desc.model_path = model; + desc.num_in = std::tuple_size::value; + desc.num_out = std::tuple_size::value; + desc.is_generic = false; + desc.disable_mem_pattern = false; + } + + /** @brief Specifies sequence of network input layers names for inference. + + The function is used to associate data of graph inputs with input layers of + network topology. Number of names has to match the number of network inputs. If a network + has only one input layer, there is no need to call it as the layer is + associated with input automatically but this doesn't prevent you from + doing it yourself. Count of names has to match to number of network inputs. + + @param layer_names std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains names of input layers. + @return the reference on modified object. + */ + Params& cfgInputLayers(const typename PortCfg::In &layer_names) { + desc.input_names.assign(layer_names.begin(), layer_names.end()); + return *this; + } + + /** @brief Specifies sequence of output layers names for inference. + + The function is used to associate data of graph outputs with output layers of + network topology. If a network has only one output layer, there is no need to call it + as the layer is associated with output automatically but this doesn't prevent + you from doing it yourself. Count of names has to match to number of network + outputs or you can set your own output but for this case you have to + additionally use @ref cfgPostProc function. + + @param layer_names std::array where N is the number of outputs + as defined in the @ref G_API_NET. Contains names of output layers. + @return the reference on modified object. + */ + Params& cfgOutputLayers(const typename PortCfg::Out &layer_names) { + desc.output_names.assign(layer_names.begin(), layer_names.end()); + return *this; + } + + /** @brief Sets a constant input. + + The function is used to set constant input. This input has to be + a prepared tensor since preprocessing is disabled for this case. You should + provide name of network layer which will receive provided data. + + @param layer_name Name of network layer. + @param data cv::Mat that contains data which will be associated with network layer. + @param hint Type of input (TENSOR). + @return the reference on modified object. + */ + Params& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR) { + desc.const_inputs[layer_name] = {data, hint}; + return *this; + } + + /** @brief Specifies mean value and standard deviation for preprocessing. + + The function is used to set mean value and standard deviation for preprocessing + of input data. + + @param m std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains mean values. + @param s std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains standard deviation values. + @return the reference on modified object. + */ + Params& cfgMeanStd(const typename PortCfg::NormCoefs &m, + const typename PortCfg::NormCoefs &s) { + desc.mean.assign(m.begin(), m.end()); + desc.stdev.assign(s.begin(), s.end()); + return *this; + } + + /** @brief Configures graph output and provides the post processing function from user. + + The function is used when you work with networks with dynamic outputs. + Since we can't know dimensions of inference result needs provide them for + construction of graph output. This dimensions can differ from inference result. + So you have to provide @ref PostProc function that gets information from inference + result and fill output which is constructed by dimensions from out_metas. + + @param out_metas Out meta information about your output (type, dimension). + @param remap_function Post processing function, which has two parameters. First is onnx + result, second is graph output. Both parameters is std::map that contain pair of + layer's name and cv::Mat. + @return the reference on modified object. + */ + Params& cfgPostProc(const std::vector &out_metas, + const PostProc &remap_function) { + desc.out_metas = out_metas; + desc.custom_post_proc = remap_function; + return *this; + } + + /** @overload + Function with a rvalue parameters. + + @param out_metas rvalue out meta information about your output (type, dimension). + @param remap_function rvalue post processing function, which has two parameters. First is onnx + result, second is graph output. Both parameters is std::map that contain pair of + layer's name and cv::Mat. + @return the reference on modified object. + */ + Params& cfgPostProc(std::vector &&out_metas, + PostProc &&remap_function) { + desc.out_metas = std::move(out_metas); + desc.custom_post_proc = std::move(remap_function); + return *this; + } + + /** @overload + The function has additional parameter names_to_remap. This parameter provides + information about output layers which will be used for inference and post + processing function. + + @param out_metas Out meta information. + @param remap_function Post processing function. + @param names_to_remap Names of output layers. network's inference will + be done on these layers. Inference's result will be processed in post processing + function using these names. + @return the reference on modified object. + */ + Params& cfgPostProc(const std::vector &out_metas, + const PostProc &remap_function, + const std::vector &names_to_remap) { + desc.out_metas = out_metas; + desc.custom_post_proc = remap_function; + desc.names_to_remap = names_to_remap; + return *this; + } + + /** @overload + Function with a rvalue parameters and additional parameter names_to_remap. + + @param out_metas rvalue out meta information. + @param remap_function rvalue post processing function. + @param names_to_remap rvalue names of output layers. network's inference will + be done on these layers. Inference's result will be processed in post processing + function using these names. + @return the reference on modified object. + */ + Params& cfgPostProc(std::vector &&out_metas, + PostProc &&remap_function, + std::vector &&names_to_remap) { + desc.out_metas = std::move(out_metas); + desc.custom_post_proc = std::move(remap_function); + desc.names_to_remap = std::move(names_to_remap); + return *this; + } + + /** @brief Specifies normalize parameter for preprocessing. + + The function is used to set normalize parameter for preprocessing of input data. + + @param normalizations std::array where N is the number of inputs + as defined in the @ref G_API_NET. Сontains bool values that enabled or disabled + normalize of input data. + @return the reference on modified object. + */ + Params& cfgNormalize(const typename PortCfg::Normalize &normalizations) { + desc.normalize.assign(normalizations.begin(), normalizations.end()); + return *this; + } + + /** @brief Adds execution provider for runtime. + + The function is used to add ONNX Runtime OpenVINO Execution Provider options. + + @param ep OpenVINO Execution Provider options. + @see cv::gapi::onnx::ep::OpenVINO. + + @return the reference on modified object. + */ + Params& cfgAddExecutionProvider(ep::OpenVINO&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + return *this; + } + + /** @brief Adds execution provider for runtime. + + The function is used to add ONNX Runtime DirectML Execution Provider options. + + @param ep DirectML Execution Provider options. + @see cv::gapi::onnx::ep::DirectML. + + @return the reference on modified object. + */ + Params& cfgAddExecutionProvider(ep::DirectML&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + return *this; + } + + /** @brief Adds execution provider for runtime. + + The function is used to add ONNX Runtime CoreML Execution Provider options. + + @param ep CoreML Execution Provider options. + @see cv::gapi::onnx::ep::CoreML. + + @return the reference on modified object. + */ + Params& cfgAddExecutionProvider(ep::CoreML&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + return *this; + } + + /** @brief Adds execution provider for runtime. + + The function is used to add ONNX Runtime CUDA Execution Provider options. + + @param ep CUDA Execution Provider options. + @see cv::gapi::onnx::ep::CUDA. + + @return the reference on modified object. + */ + Params& cfgAddExecutionProvider(ep::CUDA&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + return *this; + } + + /** @brief Adds execution provider for runtime. + + The function is used to add ONNX Runtime TensorRT Execution Provider options. + + @param ep TensorRT Execution Provider options. + @see cv::gapi::onnx::ep::TensorRT. + + @return the reference on modified object. + */ + Params& cfgAddExecutionProvider(ep::TensorRT&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + return *this; + } + + /** @brief Disables the memory pattern optimization. + + @return the reference on modified object. + */ + Params& cfgDisableMemPattern() { + desc.disable_mem_pattern = true; + return *this; + } + + /** @brief Configures session options for ONNX Runtime. + + This function is used to set various session options for the ONNX Runtime + session by accepting a map of key-value pairs. + + @param options A map of session option to be applied to the ONNX Runtime session. + @return the reference on modified object. + */ + Params& cfgSessionOptions(const std::map& options) { + desc.session_options.insert(options.begin(), options.end()); + return *this; + } + + /** @brief Configures optimization level for ONNX Runtime. + + @param opt_level [optimization level]: Valid values are 0 (disable), 1 (basic), 2 (extended), 99 (all). + Please see onnxruntime_c_api.h (enum GraphOptimizationLevel) for the full list of all optimization levels. + @return the reference on modified object. + */ + Params& cfgOptLevel(const int opt_level) { + desc.opt_level = cv::util::make_optional(opt_level); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::onnx::backend(); } + std::string tag() const { return Net::tag(); } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) + +protected: + detail::ParamDesc desc; +}; + +/* +* @brief This structure provides functions for generic network type that +* fill inference parameters. +* @see struct Generic +*/ +template<> +class Params { +public: + /** @brief Class constructor. + + Constructs Params based on input information and sets default values for other + inference description parameters. + + @param tag string tag of the network for which these parameters are intended. + @param model_path path to model file (.onnx file). + */ + Params(const std::string& tag, const std::string& model_path) + : desc{ model_path, 0u, 0u, {}, {}, {}, {}, {}, {}, {}, {}, {}, true, {}, {}, {}, {}, false, {} }, m_tag(tag) {} + + /** @see onnx::Params::cfgMeanStdDev. */ + void cfgMeanStdDev(const std::string &layer, + const cv::Scalar &m, + const cv::Scalar &s) { + desc.generic_mstd[layer] = std::make_pair(m, s); + } + + /** @see onnx::Params::cfgNormalize. */ + void cfgNormalize(const std::string &layer, bool flag) { + desc.generic_norm[layer] = flag; + } + + /** @see onnx::Params::cfgAddExecutionProvider. */ + void cfgAddExecutionProvider(ep::OpenVINO&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + } + + /** @see onnx::Params::cfgAddExecutionProvider. */ + void cfgAddExecutionProvider(ep::DirectML&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + } + + /** @see onnx::Params::cfgAddExecutionProvider. */ + void cfgAddExecutionProvider(ep::CoreML&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + } + + /** @see onnx::Params::cfgAddExecutionProvider. */ + void cfgAddExecutionProvider(ep::CUDA&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + } + + /** @see onnx::Params::cfgAddExecutionProvider. */ + void cfgAddExecutionProvider(ep::TensorRT&& ep) { + desc.execution_providers.emplace_back(std::move(ep)); + } + + /** @see onnx::Params::cfgDisableMemPattern. */ + void cfgDisableMemPattern() { + desc.disable_mem_pattern = true; + } + + /** @see onnx::Params::cfgSessionOptions. */ + void cfgSessionOptions(const std::map& options) { + desc.session_options.insert(options.begin(), options.end()); + } + +/** @see onnx::Params::cfgOptLevel. */ + void cfgOptLevel(const int opt_level) { + desc.opt_level = cv::util::make_optional(opt_level); + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::onnx::backend(); } + std::string tag() const { return m_tag; } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) +protected: + detail::ParamDesc desc; + std::string m_tag; +}; + +} // namespace onnx +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_INFER_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ov.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ov.hpp new file mode 100644 index 0000000000000000000000000000000000000000..782792489bacef55e4744822d34bf90c981a5928 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/ov.hpp @@ -0,0 +1,709 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2023 Intel Corporation + +#ifndef OPENCV_GAPI_INFER_OV_HPP +#define OPENCV_GAPI_INFER_OV_HPP + +#include + +#include +#include // GAPI_EXPORTS +#include // GKernelType[M], GBackend +#include // Generic + +#include + +namespace cv { +namespace gapi { + +/** + * @brief This namespace contains G-API OpenVINO 2.0 backend functions, + * structures, and symbols. + */ +namespace ov { + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +namespace detail { + +template +using AttrMap = std::map; +// NB: This type is supposed to be used to hold in/out layers +// attributes such as precision, layout, shape etc. +// +// User can provide attributes either: +// 1. cv::util::monostate - No value specified explicitly. +// 2. Attr - value specified explicitly that should be broadcasted to all layers. +// 3. AttrMap[str->T] - map specifies value for particular layer. +template +using LayerVariantAttr = cv::util::variant< cv::util::monostate + , AttrMap + , Attr>; + +struct ParamDesc { + struct Model { + + Model(const std::string &model_path_, + const std::string &bin_path_) + : model_path(model_path_), bin_path(bin_path_) { + } + + std::string model_path; + std::string bin_path; + + LayerVariantAttr input_tensor_layout; + LayerVariantAttr input_model_layout; + LayerVariantAttr output_tensor_layout; + LayerVariantAttr output_model_layout; + LayerVariantAttr output_tensor_precision; + + LayerVariantAttr> new_shapes; + + LayerVariantAttr> mean_values; + LayerVariantAttr> scale_values; + + LayerVariantAttr interpolation; + }; + + struct CompiledModel { + std::string blob_path; + }; + + using Kind = cv::util::variant; + + ParamDesc(Kind &&kind_, + const std::string &device_, + const bool is_generic_, + const size_t num_in_, + const size_t num_out_) + : kind(std::move(kind_)), device(device_), + is_generic(is_generic_), + num_in(num_in_), num_out(num_out_) { + } + + Kind kind; + + std::string device; + bool is_generic; + + std::size_t num_in; + std::size_t num_out; + + std::vector input_names; + std::vector output_names; + + using PluginConfigT = std::map; + PluginConfigT config; + + size_t nireq = 1; +}; + +// NB: Just helper to avoid code duplication. +static detail::ParamDesc::Model& +getModelToSetAttrOrThrow(detail::ParamDesc::Kind &kind, + const std::string &attr_name) { + if (cv::util::holds_alternative(kind)) { + cv::util::throw_error( + std::logic_error("Specifying " + attr_name + " isn't" + " possible for compiled model.")); + } + GAPI_Assert(cv::util::holds_alternative(kind)); + return cv::util::get(kind); +} + +} // namespace detail + +/** + * @brief This structure provides functions + * that fill inference parameters for "OpenVINO Toolkit" model. + */ +template struct Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and specifies default values for other + inference description parameters. Model is loaded and compiled using "OpenVINO Toolkit". + + @param model_path Path to a model. + @param bin_path Path to a data file. + For IR format (*.bin): + If path is empty, will try to read a bin file with the same name as xml. + If the bin file with the same name is not found, will load IR without weights. + For PDPD (*.pdmodel) and ONNX (*.onnx) formats bin_path isn't used. + @param device target device to use. + */ + Params(const std::string &model_path, + const std::string &bin_path, + const std::string &device) + : m_desc( detail::ParamDesc::Kind{detail::ParamDesc::Model{model_path, bin_path}} + , device + , false /* is generic */ + , std::tuple_size::value + , std::tuple_size::value) { + } + + /** @overload + Use this constructor to work with pre-compiled network. + Model is imported from a pre-compiled blob. + + @param blob_path path to the compiled model (*.blob). + @param device target device to use. + */ + Params(const std::string &blob_path, + const std::string &device) + : m_desc( detail::ParamDesc::Kind{detail::ParamDesc::CompiledModel{blob_path}} + , device + , false /* is generic */ + , std::tuple_size::value + , std::tuple_size::value) { + } + + /** @brief Specifies sequence of network input layers names for inference. + + The function is used to associate cv::gapi::infer<> inputs with the model inputs. + Number of names has to match the number of network inputs as defined in G_API_NET(). + In case a network has only single input layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains names of input layers. + @return reference to this parameter structure. + */ + Params& cfgInputLayers(const std::vector &layer_names) { + m_desc.input_names = layer_names; + return *this; + } + + /** @brief Specifies sequence of network output layers names for inference. + + The function is used to associate cv::gapi::infer<> outputs with the model outputs. + Number of names has to match the number of network outputs as defined in G_API_NET(). + In case a network has only single output layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of outputs + as defined in the @ref G_API_NET. Contains names of output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputLayers(const std::vector &layer_names) { + m_desc.output_names = layer_names; + return *this; + } + + /** @brief Specifies OpenVINO plugin configuration. + + The function is used to set configuration for OpenVINO plugin. Some parameters + can be different for each plugin. Please follow https://docs.openvinotoolkit.org/latest/index.html + to check information about specific plugin. + + @param config Map of pairs: (config parameter name, config parameter value). + @return reference to this parameter structure. + */ + Params& cfgPluginConfig(const detail::ParamDesc::PluginConfigT &config) { + m_desc.config = config; + return *this; + } + + /** @brief Specifies tensor layout for an input layer. + + The function is used to set tensor layout for an input layer. + + @param layout Tensor layout ("NCHW", "NWHC", etc) + will be applied to all input layers. + @return reference to this parameter structure. + */ + Params& cfgInputTensorLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") + .input_tensor_layout = std::move(layout); + return *this; + } + + /** @overload + @param layout_map Map of pairs: name of corresponding input layer + and its tensor layout represented in std::string ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgInputTensorLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") + .input_tensor_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies model layout for an input layer. + + The function is used to set model layout for an input layer. + + @param layout Model layout ("NCHW", "NHWC", etc) + will be applied to all input layers. + @return reference to this parameter structure. + */ + Params& cfgInputModelLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input model layout") + .input_model_layout = std::move(layout); + return *this; + } + + /** @overload + @param layout_map Map of pairs: name of corresponding input layer + and its model layout ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgInputModelLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input model layout") + .input_model_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies tensor layout for an output layer. + + The function is used to set tensor layout for an output layer. + + @param layout Tensor layout ("NCHW", "NWHC", etc) + will be applied to all output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputTensorLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor layout") + .output_tensor_layout = std::move(layout); + return *this; + } + + /** @overload + @param layout_map Map of pairs: name of corresponding output layer + and its tensor layout represented in std::string ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgOutputTensorLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor layout") + .output_tensor_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies model layout for an output layer. + + The function is used to set model layout for an output layer. + + @param layout Model layout ("NCHW", "NHWC", etc) + will be applied to all output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputModelLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output model layout") + .output_model_layout = std::move(layout); + return *this; + } + + /** @overload + @param layout_map Map of pairs: name of corresponding output layer + and its model layout ("NCHW", "NHWC", etc) + @return reference to this parameter structure. + */ + Params& + cfgOutputModelLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output model layout") + .output_model_layout = std::move(layout_map); + return *this; + } + + /** @brief Specifies tensor precision for an output layer. + + The function is used to set tensor precision for an output layer.. + + @param precision Precision in OpenCV format (CV_8U, CV_32F, ...) + will be applied to all output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputTensorPrecision(int precision) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor precision") + .output_tensor_precision = precision; + return *this; + } + + /** @overload + + @param precision_map Map of pairs: name of corresponding output layer + and its precision in OpenCV format (CV_8U, CV_32F, ...) + @return reference to this parameter structure. + */ + Params& + cfgOutputTensorPrecision(detail::AttrMap precision_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor precision") + .output_tensor_precision = std::move(precision_map); + return *this; + } + + /** @brief Specifies the new shape for input layers. + + The function is used to set new shape for input layers. + + @param new_shape New shape will be applied to all input layers. + @return reference to this parameter structure. + */ + Params& + cfgReshape(std::vector new_shape) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape") + .new_shapes = std::move(new_shape); + return *this; + } + + /** @overload + + @param new_shape_map Map of pairs: name of corresponding output layer + and its new shape. + @return reference to this parameter structure. + */ + Params& + cfgReshape(detail::AttrMap> new_shape_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape") + .new_shapes = std::move(new_shape_map); + return *this; + } + + /** @brief Specifies number of asynchronous inference requests. + + @param nireq Number of inference asynchronous requests. + @return reference to this parameter structure. + */ + Params& cfgNumRequests(const size_t nireq) { + if (nireq == 0) { + cv::util::throw_error( + std::logic_error("Number of inference requests" + " must be greater than zero.")); + } + m_desc.nireq = nireq; + return *this; + } + + /** @brief Specifies mean values for preprocessing. + * + The function is used to set mean values for input layer preprocessing. + + @param mean_values Float vector contains mean values + @return reference to this parameter structure. + */ + Params& cfgMean(std::vector mean_values) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "mean values") + .mean_values = std::move(mean_values); + return *this; + } + + /** @overload + + @param mean_map Map of pairs: name of corresponding input layer + and its mean values. + @return reference to this parameter structure. + */ + Params& cfgMean(detail::AttrMap> mean_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "mean values") + .mean_values = std::move(mean_map); + return *this; + } + + /** @brief Specifies scale values for preprocessing. + * + The function is used to set scale values for input layer preprocessing. + + @param scale_values Float vector contains scale values + @return reference to this parameter structure. + */ + Params& cfgScale(std::vector scale_values) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "scale values") + .scale_values = std::move(scale_values); + return *this; + } + + /** @overload + + @param scale_map Map of pairs: name of corresponding input layer + and its mean values. + @return reference to this parameter structure. + */ + Params& cfgScale(detail::AttrMap> scale_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "scale values") + .scale_values = std::move(scale_map); + return *this; + } + + /** @brief Specifies resize interpolation algorithm. + * + The function is used to configure resize preprocessing for input layer. + + @param interpolation Resize interpolation algorithm. + Supported algorithms: #INTER_NEAREST, #INTER_LINEAR, #INTER_CUBIC. + @return reference to this parameter structure. + */ + Params& cfgResize(int interpolation) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "resize preprocessing") + .interpolation = std::move(interpolation); + return *this; + } + + /** @overload + + @param interpolation Map of pairs: name of corresponding input layer + and its resize algorithm. + @return reference to this parameter structure. + */ + Params& cfgResize(detail::AttrMap interpolation) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "resize preprocessing") + .interpolation = std::move(interpolation); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::ov::backend(); } + std::string tag() const { return Net::tag(); } + cv::util::any params() const { return { m_desc }; } + // END(G-API's network parametrization API) + +protected: + detail::ParamDesc m_desc; +}; + +/* +* @brief This structure provides functions for generic network type that +* fill inference parameters. +* @see struct Generic +*/ +template<> +class Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and specifies default values for other + inference description parameters. Model is loaded and compiled using "OpenVINO Toolkit". + + @param tag string tag of the network for which these parameters are intended. + @param model_path Path to a model. + @param bin_path Path to a data file. + For IR format (*.bin): + If path is empty, will try to read a bin file with the same name as xml. + If the bin file with the same name is not found, will load IR without weights. + For PDPD (*.pdmodel) and ONNX (*.onnx) formats bin_path isn't used. + @param device target device to use. + */ + Params(const std::string &tag, + const std::string &model_path, + const std::string &bin_path, + const std::string &device) + : m_tag(tag), + m_desc( detail::ParamDesc::Kind{detail::ParamDesc::Model{model_path, bin_path}} + , device + , true /* is generic */ + , 0u + , 0u) { + } + + /** @overload + + This constructor for pre-compiled networks. Model is imported from pre-compiled + blob. + + @param tag string tag of the network for which these parameters are intended. + @param blob_path path to the compiled model (*.blob). + @param device target device to use. + */ + Params(const std::string &tag, + const std::string &blob_path, + const std::string &device) + : m_tag(tag), + m_desc( detail::ParamDesc::Kind{detail::ParamDesc::CompiledModel{blob_path}} + , device + , true /* is generic */ + , 0u + , 0u) { + } + + /** @see ov::Params::cfgPluginConfig. */ + Params& cfgPluginConfig(const detail::ParamDesc::PluginConfigT &config) { + m_desc.config = config; + return *this; + } + + /** @see ov::Params::cfgInputTensorLayout. */ + Params& cfgInputTensorLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") + .input_tensor_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgInputTensorLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") + .input_tensor_layout = std::move(layout_map); + return *this; + } + + /** @see ov::Params::cfgInputModelLayout. */ + Params& cfgInputModelLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input model layout") + .input_model_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgInputModelLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "input model layout") + .input_model_layout = std::move(layout_map); + return *this; + } + + /** @see ov::Params::cfgOutputTensorLayout. */ + Params& cfgOutputTensorLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor layout") + .output_tensor_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgOutputTensorLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor layout") + .output_tensor_layout = std::move(layout_map); + return *this; + } + + /** @see ov::Params::cfgOutputModelLayout. */ + Params& cfgOutputModelLayout(std::string layout) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output model layout") + .output_model_layout = std::move(layout); + return *this; + } + + /** @overload */ + Params& + cfgOutputModelLayout(detail::AttrMap layout_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output model layout") + .output_model_layout = std::move(layout_map); + return *this; + } + + /** @see ov::Params::cfgOutputTensorPrecision. */ + Params& cfgOutputTensorPrecision(int precision) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor precision") + .output_tensor_precision = precision; + return *this; + } + + /** @overload */ + Params& + cfgOutputTensorPrecision(detail::AttrMap precision_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "output tensor precision") + .output_tensor_precision = std::move(precision_map); + return *this; + } + + /** @see ov::Params::cfgReshape. */ + Params& cfgReshape(std::vector new_shape) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape") + .new_shapes = std::move(new_shape); + return *this; + } + + /** @overload */ + Params& + cfgReshape(detail::AttrMap> new_shape_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape") + .new_shapes = std::move(new_shape_map); + return *this; + } + + /** @see ov::Params::cfgNumRequests. */ + Params& cfgNumRequests(const size_t nireq) { + if (nireq == 0) { + cv::util::throw_error( + std::logic_error("Number of inference requests" + " must be greater than zero.")); + } + m_desc.nireq = nireq; + return *this; + } + + /** @see ov::Params::cfgMean. */ + Params& cfgMean(std::vector mean_values) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "mean values") + .mean_values = std::move(mean_values); + return *this; + } + + /** @overload */ + Params& cfgMean(detail::AttrMap> mean_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "mean values") + .mean_values = std::move(mean_map); + return *this; + } + + /** @see ov::Params::cfgScale. */ + Params& cfgScale(std::vector scale_values) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "scale values") + .scale_values = std::move(scale_values); + return *this; + } + + /** @overload */ + Params& cfgScale(detail::AttrMap> scale_map) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "scale values") + .scale_values = std::move(scale_map); + return *this; + } + + /** @see ov::Params::cfgResize. */ + Params& cfgResize(int interpolation) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "resize preprocessing") + .interpolation = std::move(interpolation); + return *this; + } + + /** @overload */ + Params& cfgResize(detail::AttrMap interpolation) { + detail::getModelToSetAttrOrThrow(m_desc.kind, "resize preprocessing") + .interpolation = std::move(interpolation); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::ov::backend(); } + std::string tag() const { return m_tag; } + cv::util::any params() const { return { m_desc }; } + // END(G-API's network parametrization API) + +protected: + std::string m_tag; + detail::ParamDesc m_desc; +}; + +} // namespace ov + +namespace wip { namespace ov { +/** + * @brief Ask G-API OpenVINO backend to run only inference of model provided. + * + * G-API OpenVINO backend will perform only the inference of the model provided + * without populating input and copying back output data. + * This mode is used to evaluate the pure inference performance of the model without + * taking into account the i/o data transfer. + */ +struct benchmark_mode { }; + +} // namespace ov +} // namespace wip + +} // namespace gapi + +namespace detail +{ + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.wip.ov.benchmark_mode"; } + }; +} + +} // namespace cv + +#endif // OPENCV_GAPI_INFER_OV_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/parsers.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/parsers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e39d6fd4c6a2673f401d2ddfa718d0da5b64b0d2 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/infer/parsers.hpp @@ -0,0 +1,138 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + + +#ifndef OPENCV_GAPI_PARSERS_HPP +#define OPENCV_GAPI_PARSERS_HPP + +#include // std::tuple + +#include +#include + +namespace cv { namespace gapi { +namespace nn { +namespace parsers { + using GRects = GArray; + using GDetections = std::tuple, GArray>; + + G_TYPED_KERNEL(GParseSSDBL, , float, int)>, + "org.opencv.nn.parsers.parseSSD_BL") { + static std::tuple outMeta(const GMatDesc&, const GOpaqueDesc&, float, int) { + return std::make_tuple(empty_array_desc(), empty_array_desc()); + } + }; + + G_TYPED_KERNEL(GParseSSD, , float, bool, bool)>, + "org.opencv.nn.parsers.parseSSD") { + static GArrayDesc outMeta(const GMatDesc&, const GOpaqueDesc&, float, bool, bool) { + return empty_array_desc(); + } + }; + + G_TYPED_KERNEL(GParseYolo, , float, float, std::vector)>, + "org.opencv.nn.parsers.parseYolo") { + static std::tuple outMeta(const GMatDesc&, const GOpaqueDesc&, + float, float, const std::vector&) { + return std::make_tuple(empty_array_desc(), empty_array_desc()); + } + static const std::vector& defaultAnchors() { + static std::vector anchors { + 0.57273f, 0.677385f, 1.87446f, 2.06253f, 3.33843f, 5.47434f, 7.88282f, 3.52778f, 9.77052f, 9.16828f + }; + return anchors; + } + }; +} // namespace parsers +} // namespace nn + +/** @brief Parses output of SSD network. + +Extracts detection information (box, confidence, label) from SSD output and +filters it by given confidence and label. + +@note Function textual ID is "org.opencv.nn.parsers.parseSSD_BL" + +@param in Input CV_32F tensor with {1,1,N,7} dimensions. +@param inSz Size to project detected boxes to (size of the input image). +@param confidenceThreshold If confidence of the +detection is smaller than confidence threshold, detection is rejected. +@param filterLabel If provided (!= -1), only detections with +given label will get to the output. +@return a tuple with a vector of detected boxes and a vector of appropriate labels. +*/ +GAPI_EXPORTS_W std::tuple, GArray> parseSSD(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold = 0.5f, + const int filterLabel = -1); + +/** @brief Parses output of SSD network. + +Extracts detection information (box, confidence) from SSD output and +filters it by given confidence and by going out of bounds. + +@note Function textual ID is "org.opencv.nn.parsers.parseSSD" + +@param in Input CV_32F tensor with {1,1,N,7} dimensions. +@param inSz Size to project detected boxes to (size of the input image). +@param confidenceThreshold If confidence of the +detection is smaller than confidence threshold, detection is rejected. +@param alignmentToSquare If provided true, bounding boxes are extended to squares. +The center of the rectangle remains unchanged, the side of the square is +the larger side of the rectangle. +@param filterOutOfBounds If provided true, out-of-frame boxes are filtered. +@return a vector of detected bounding boxes. +*/ +GAPI_EXPORTS_W GArray parseSSD(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold, + const bool alignmentToSquare, + const bool filterOutOfBounds); + +/** @brief Parses output of Yolo network. + +Extracts detection information (box, confidence, label) from Yolo output, +filters it by given confidence and performs non-maximum suppression for overlapping boxes. + +@note Function textual ID is "org.opencv.nn.parsers.parseYolo" + +@param in Input CV_32F tensor with {1,13,13,N} dimensions, N should satisfy: +\f[\texttt{N} = (\texttt{num_classes} + \texttt{5}) * \texttt{5},\f] +where num_classes - a number of classes Yolo network was trained with. +@param inSz Size to project detected boxes to (size of the input image). +@param confidenceThreshold If confidence of the +detection is smaller than confidence threshold, detection is rejected. +@param nmsThreshold Non-maximum suppression threshold which controls minimum +relative box intersection area required for rejecting the box with a smaller confidence. +If 1.f, nms is not performed and no boxes are rejected. +@param anchors Anchors Yolo network was trained with. +@note The default anchor values are specified for YOLO v2 Tiny as described in Intel Open Model Zoo +documentation. +@return a tuple with a vector of detected boxes and a vector of appropriate labels. +*/ +GAPI_EXPORTS_W std::tuple, GArray> parseYolo(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold = 0.5f, + const float nmsThreshold = 0.5f, + const std::vector& anchors + = nn::parsers::GParseYolo::defaultAnchors()); + +} // namespace gapi +} // namespace cv + +// Reimport parseSSD & parseYolo under their initial namespace +namespace cv { +namespace gapi { +namespace streaming { + +using cv::gapi::parseSSD; +using cv::gapi::parseYolo; + +} // namespace streaming +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_PARSERS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/media.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/media.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1470f00d042e6434cbbf59f34fbf5b752ef581ba --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/media.hpp @@ -0,0 +1,258 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_MEDIA_HPP +#define OPENCV_GAPI_MEDIA_HPP + +#include // unique_ptr<>, shared_ptr<> +#include // array<> +#include // function<> +#include // forward<>() + +#include +#include + +// Forward declaration +namespace cv { +namespace gapi { +namespace s11n { +struct IOStream; +struct IIStream; +} // namespace s11n +} // namespace gapi +} // namespace cv + +namespace cv { + +/** \addtogroup gapi_data_structures + * @{ + * + * @brief Extra G-API data structures used to pass input/output data + * to the graph for processing. + */ + +/** + * @brief cv::MediaFrame class represents an image/media frame + * obtained from an external source. + * + * cv::MediaFrame represents image data as specified in + * cv::MediaFormat. cv::MediaFrame is designed to be a thin wrapper over some + * external memory of buffer; the class itself provides an uniform + * interface over such types of memory. cv::MediaFrame wraps data from + * a camera driver or from a media codec and provides an abstraction + * layer over this memory to G-API. MediaFrame defines a compact interface + * to access and manage the underlying data; the implementation is + * fully defined by the associated Adapter (which is usually + * user-defined). + * + * @sa cv::RMat + */ +class GAPI_EXPORTS MediaFrame { +public: + /// This enum defines different types of cv::MediaFrame provided + /// access to the underlying data. Note that different flags can't + /// be combined in this version. + enum class Access { + R, ///< Access data for reading + W, ///< Access data for writing + }; + class IAdapter; + class View; + using AdapterPtr = std::unique_ptr; + + /** + * @brief Constructs an empty MediaFrame + * + * The constructed object has no any data associated with it. + */ + MediaFrame(); + + /** + * @brief Constructs a MediaFrame with the given + * Adapter. MediaFrame takes ownership over the passed adapter. + * + * @param p an unique pointer to instance of IAdapter derived class. + */ + explicit MediaFrame(AdapterPtr &&p); + + /** + * @overload + * @brief Constructs a MediaFrame with the given parameters for + * the Adapter. The adapter of type `T` is costructed on the fly. + * + * @param args list of arguments to construct an adapter of type + * `T`. + */ + template static cv::MediaFrame Create(Args&&... args); + + /** + * @brief Obtain access to the underlying data with the given + * mode. + * + * Depending on the associated Adapter and the data wrapped, this + * method may be cheap (e.g., the underlying memory is local) or + * costly (if the underlying memory is external or device + * memory). + * + * @param mode an access mode flag + * @return a MediaFrame::View object. The views should be handled + * carefully, refer to the MediaFrame::View documentation for details. + */ + View access(Access mode) const; + + /** + * @brief Returns a media frame descriptor -- the information + * about the media format, dimensions, etc. + * @return a cv::GFrameDesc + */ + cv::GFrameDesc desc() const; + + // FIXME: design a better solution + // Should be used only if the actual adapter provides implementation + /// @private -- exclude from the OpenCV documentation for now. + cv::util::any blobParams() const; + + /** + * @brief Casts and returns the associated MediaFrame adapter to + * the particular adapter type `T`, returns nullptr if the type is + * different. + * + * This method may be useful if the adapter type is known by the + * caller, and some lower level access to the memory is required. + * Depending on the memory type, it may be more efficient than + * access(). + * + * @return a pointer to the adapter object, nullptr if the adapter + * type is different. + */ + template T* get() const { + static_assert(std::is_base_of::value, + "T is not derived from cv::MediaFrame::IAdapter!"); + auto* adapter = getAdapter(); + GAPI_Assert(adapter != nullptr); + return dynamic_cast(adapter); + } + + /** + * @brief Serialize MediaFrame's data to a byte array. + * + * @note The actual logic is implemented by frame's adapter class. + * Does nothing by default. + * + * @param os Bytestream to store serialized MediaFrame data in. + */ + void serialize(cv::gapi::s11n::IOStream& os) const; + +private: + struct Priv; + std::shared_ptr m; + IAdapter* getAdapter() const; +}; + +template +inline cv::MediaFrame cv::MediaFrame::Create(Args&&... args) { + std::unique_ptr ptr(new T(std::forward(args)...)); + return cv::MediaFrame(std::move(ptr)); +} + +/** + * @brief Provides access to the MediaFrame's underlying data. + * + * This object contains the necessary information to access the pixel + * data of the associated MediaFrame: arrays of pointers and strides + * (distance between every plane row, in bytes) for every image + * plane, as defined in cv::MediaFormat. + * There may be up to four image planes in MediaFrame. + * + * Depending on the MediaFrame::Access flag passed in + * MediaFrame::access(), a MediaFrame::View may be read- or + * write-only. + * + * Depending on the MediaFrame::IAdapter implementation associated + * with the parent MediaFrame, writing to memory with + * MediaFrame::Access::R flag may have no effect or lead to + * undefined behavior. Same applies to reading the memory with + * MediaFrame::Access::W flag -- again, depending on the IAdapter + * implementation, the host-side buffer the view provides access to + * may have no current data stored in (so in-place editing of the + * buffer contents may not be possible). + * + * MediaFrame::View objects must be handled carefully, as an external + * resource associated with MediaFrame may be locked for the time the + * MediaFrame::View object exists. Obtaining MediaFrame::View should + * be seen as "map" and destroying it as "unmap" in the "map/unmap" + * idiom (applicable to OpenCL, device memory, remote + * memory). + * + * When a MediaFrame buffer is accessed for writing, and the memory + * under MediaFrame::View::Ptrs is altered, the data synchronization + * of a host-side and device/remote buffer is not guaranteed until the + * MediaFrame::View is destroyed. In other words, the real data on the + * device or in a remote target may be updated at the MediaFrame::View + * destruction only -- but it depends on the associated + * MediaFrame::IAdapter implementation. + */ +class GAPI_EXPORTS MediaFrame::View final { +public: + static constexpr const size_t MAX_PLANES = 4; + using Ptrs = std::array; + using Strides = std::array; // in bytes + using Callback = std::function; + + /// @private + View(Ptrs&& ptrs, Strides&& strs, Callback &&cb = [](){}); + + /// @private + View(const View&) = delete; + + /// @private + View(View&&) = default; + + /// @private + View& operator = (const View&) = delete; + + ~View(); + + Ptrs ptr; ///< Array of image plane pointers + Strides stride; ///< Array of image plane strides, in bytes. + +private: + Callback m_cb; +}; + +/** + * @brief An interface class for MediaFrame data adapters. + * + * Implement this interface to wrap media data in the MediaFrame. It + * makes sense to implement this class if there is a custom + * cv::gapi::wip::IStreamSource defined -- in this case, a stream + * source can produce MediaFrame objects with this adapter and the + * media data may be passed to graph without any copy. For example, a + * GStreamer-based stream source can implement an adapter over + * `GstBuffer` and G-API will transparently use it in the graph. + */ +class GAPI_EXPORTS MediaFrame::IAdapter { +public: + virtual ~IAdapter() = 0; + virtual cv::GFrameDesc meta() const = 0; + virtual MediaFrame::View access(MediaFrame::Access) = 0; + // FIXME: design a better solution + // The default implementation does nothing + virtual cv::util::any blobParams() const; + virtual void serialize(cv::gapi::s11n::IOStream&) { + GAPI_Error("Generic serialize method of MediaFrame::IAdapter does nothing by default. " + "Please, implement it in derived class to properly serialize the object."); + } + virtual void deserialize(cv::gapi::s11n::IIStream&) { + GAPI_Error("Generic deserialize method of MediaFrame::IAdapter does nothing by default. " + "Please, implement it in derived class to properly deserialize the object."); + } +}; +/** @} */ + +} //namespace cv + +#endif // OPENCV_GAPI_MEDIA_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/infer.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/infer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4a1b9f6db6a23cb710778561e66620108fb24d7a --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/infer.hpp @@ -0,0 +1,66 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2022 Intel Corporation + +#ifndef OPENCV_GAPI_OAK_INFER_HPP +#define OPENCV_GAPI_OAK_INFER_HPP + +#include +#include +#include +#include + +#include +#include + +#include // GAPI_EXPORTS +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace oak { + +namespace detail { +/** +* @brief This structure contains description of inference parameters +* which is specific to OAK models. +*/ +struct ParamDesc { + std::string blob_file; +}; +} // namespace detail + +/** + * Contains description of inference parameters and kit of functions that + * fill this parameters. + */ +template class Params { +public: + /** @brief Class constructor. + + Constructs Params based on model information and sets default values for other + inference description parameters. + + @param model Path to model (.blob file) + */ + explicit Params(const std::string &model) { + desc.blob_file = model; + }; + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::oak::backend(); } + std::string tag() const { return Net::tag(); } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) + +protected: + detail::ParamDesc desc; +}; + +} // namespace oak +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_OAK_INFER_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/oak.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/oak.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b56b8a3658be15cbebda9d07bce967fd7616b88 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/oak/oak.hpp @@ -0,0 +1,158 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_OAK_HPP +#define OPENCV_GAPI_OAK_HPP + +#include // IStreamSource +#include // GKernelPackage +#include // GOptRunArgsP + +namespace cv { +namespace gapi { +namespace oak { + +// FIXME: copypasted from dai library +struct EncoderConfig { + /** + * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265) + */ + enum class RateControlMode: int { CBR, VBR }; + + /** + * Encoding profile, H264, H265 or MJPEG + */ + enum class Profile: int { H264_BASELINE, H264_HIGH, H264_MAIN, H265_MAIN, MJPEG }; + /** + * Specifies preferred bitrate (kb) of compressed output bitstream + */ + std::int32_t bitrate = 8000; + /** + * Every x number of frames a keyframe will be inserted + */ + std::int32_t keyframeFrequency = 30; + /** + * Specifies maximum bitrate (kb) of compressed output bitstream + */ + std::int32_t maxBitrate = 8000; + /** + * Specifies number of B frames to be inserted + */ + std::int32_t numBFrames = 0; + /** + * This options specifies how many frames are available in this nodes pool (can help if + * receiver node is slow at consuming + */ + std::uint32_t numFramesPool = 4; + /** + * Encoding profile, H264, H265 or MJPEG + */ + Profile profile = Profile::H265_MAIN; + /** + * Value between 0-100% (approximates quality) + */ + std::int32_t quality = 80; + /** + * Lossless mode ([M]JPEG only) + */ + bool lossless = false; + /** + * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265) + */ + RateControlMode rateCtrlMode = RateControlMode::CBR; + /** + * Input and compressed output frame width + */ + std::int32_t width = 1920; + /** + * Input and compressed output frame height + */ + std::int32_t height = 1080; + /** + * Frame rate + */ + float frameRate = 30.0f; +}; + +G_API_OP(GEncFrame, (GFrame, EncoderConfig)>, "org.opencv.oak.enc_frame") { + static GArrayDesc outMeta(const GFrameDesc&, const EncoderConfig&) { + return cv::empty_array_desc(); + } +}; + +G_API_OP(GSobelXY, , "org.opencv.oak.sobelxy") { + static GFrameDesc outMeta(const GFrameDesc& in, const cv::Mat&, const cv::Mat&) { + return in; + } +}; + +G_API_OP(GCopy, , "org.opencv.oak.copy") { + static GFrameDesc outMeta(const GFrameDesc& in) { + return in; + } +}; + +// FIXME: add documentation on operations below + +GAPI_EXPORTS GArray encode(const GFrame& in, const EncoderConfig&); + +GAPI_EXPORTS GFrame sobelXY(const GFrame& in, + const cv::Mat& hk, + const cv::Mat& vk); + +GAPI_EXPORTS GFrame copy(const GFrame& in); + +// OAK backend & kernels //////////////////////////////////////////////////////// +GAPI_EXPORTS cv::gapi::GBackend backend(); +GAPI_EXPORTS cv::gapi::GKernelPackage kernels(); + +// Camera object /////////////////////////////////////////////////////////////// + +struct GAPI_EXPORTS ColorCameraParams { + /** + * Format of the frame one gets from the camera + */ + bool interleaved = false; + + // FIXME: extend + enum class BoardSocket: int { RGB, BGR }; + + BoardSocket board_socket = BoardSocket::RGB; + + // FIXME: extend + enum class Resolution: int { THE_1080_P }; + + Resolution resolution = Resolution::THE_1080_P; +}; + +class GAPI_EXPORTS ColorCamera: public cv::gapi::wip::IStreamSource { + cv::MediaFrame m_dummy; + ColorCameraParams m_params; + + virtual bool pull(cv::gapi::wip::Data &data) override; + virtual GMetaArg descr_of() const override; + +public: + ColorCamera(); + explicit ColorCamera(const ColorCameraParams& params); +}; + +} // namespace oak +} // namespace gapi + +namespace detail { +template<> struct CompileArgTag { + static const char* tag() { return "gapi.oak.colorCameraParams"; } +}; + +template<> struct CompileArgTag { + static const char* tag() { return "gapi.oak.encoderConfig"; } +}; +} // namespace detail + +} // namespace cv + +#endif // OPENCV_GAPI_OAK_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b79aace0ca7b7a6ccffbb23c972922b2392fcca3 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/core.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OCL_CORE_API_HPP +#define OPENCV_GAPI_OCL_CORE_API_HPP + +#include // GAPI_EXPORTS +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace core { +namespace ocl { + +GAPI_EXPORTS_W cv::GKernelPackage kernels(); + +} // namespace ocl +} // namespace core +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_OCL_CORE_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/goclkernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/goclkernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b09082282f55bef4e89a49e5fec7d7329c1ea967 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/goclkernel.hpp @@ -0,0 +1,260 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GOCLKERNEL_HPP +#define OPENCV_GAPI_GOCLKERNEL_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +// FIXME: namespace scheme for backends? +namespace cv { + +namespace gimpl +{ + // Forward-declare an internal class + class GOCLExecutable; +} // namespace gimpl + +namespace gapi +{ +/** + * @brief This namespace contains G-API OpenCL backend functions, structures, and symbols. + */ +namespace ocl +{ + /** + * \addtogroup gapi_std_backends G-API Standard Backends + * @{ + */ + /** + * @brief Get a reference to OCL backend. + * + * At the moment, the OCL backend is built atop of OpenCV + * "Transparent API" (T-API), see cv::UMat for details. + * + * @sa gapi_std_backends + */ + GAPI_EXPORTS cv::gapi::GBackend backend(); + /** @} */ +} // namespace ocl +} // namespace gapi + + +// Represents arguments which are passed to a wrapped OCL function +// FIXME: put into detail? +class GAPI_EXPORTS GOCLContext +{ +public: + // Generic accessor API + template + const T& inArg(int input) { return m_args.at(input).get(); } + + // Syntax sugar + const cv::UMat& inMat(int input); + cv::UMat& outMatR(int output); // FIXME: Avoid cv::Mat m = ctx.outMatR() + + const cv::Scalar& inVal(int input); + cv::Scalar& outValR(int output); // FIXME: Avoid cv::Scalar s = ctx.outValR() + template std::vector& outVecR(int output) // FIXME: the same issue + { + return outVecRef(output).wref(); + } + template T& outOpaqueR(int output) // FIXME: the same issue + { + return outOpaqueRef(output).wref(); + } + +protected: + detail::VectorRef& outVecRef(int output); + detail::OpaqueRef& outOpaqueRef(int output); + + std::vector m_args; + std::unordered_map m_results; + + + friend class gimpl::GOCLExecutable; +}; + +class GAPI_EXPORTS GOCLKernel +{ +public: + // This function is kernel's execution entry point (does the processing work) + using F = std::function; + + GOCLKernel(); + explicit GOCLKernel(const F& f); + + void apply(GOCLContext &ctx); + +protected: + F m_f; +}; + +// FIXME: This is an ugly ad-hoc implementation. TODO: refactor + +namespace detail +{ +template struct ocl_get_in; +template<> struct ocl_get_in +{ + static cv::UMat get(GOCLContext &ctx, int idx) { return ctx.inMat(idx); } +}; +template<> struct ocl_get_in +{ + static cv::Scalar get(GOCLContext &ctx, int idx) { return ctx.inVal(idx); } +}; +template struct ocl_get_in > +{ + static const std::vector& get(GOCLContext &ctx, int idx) { return ctx.inArg(idx).rref(); } +}; +template<> struct ocl_get_in +{ + static cv::MediaFrame get(GOCLContext &ctx, int idx) { return ctx.inArg(idx); } +}; +template struct ocl_get_in > +{ + static const U& get(GOCLContext &ctx, int idx) { return ctx.inArg(idx).rref(); } +}; +template struct ocl_get_in +{ + static T get(GOCLContext &ctx, int idx) { return ctx.inArg(idx); } +}; + +struct tracked_cv_umat{ + //TODO Think if T - API could reallocate UMat to a proper size - how do we handle this ? + //tracked_cv_umat(cv::UMat& m) : r{(m)}, original_data{m.getMat(ACCESS_RW).data} {} + tracked_cv_umat(cv::UMat& m) : r(m), original_data{ nullptr } {} + cv::UMat &r; // FIXME: It was a value (not a reference) before. + // Actually OCL backend should allocate its internal data! + uchar* original_data; + + operator cv::UMat& (){ return r;} + void validate() const{ + //if (r.getMat(ACCESS_RW).data != original_data) + //{ + // util::throw_error + // (std::logic_error + // ("OpenCV kernel output parameter was reallocated. \n" + // "Incorrect meta data was provided ?")); + //} + + } +}; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // unreachable code +#endif +template +void postprocess_ocl(Outputs&... outs) +{ + struct + { + void operator()(tracked_cv_umat* bm) { bm->validate(); } + void operator()(...) { } + + } validate; + //dummy array to unfold parameter pack + int dummy[] = { 0, (validate(&outs), 0)... }; + cv::util::suppress_unused_warning(dummy); +} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +template struct ocl_get_out; +template<> struct ocl_get_out +{ + static tracked_cv_umat get(GOCLContext &ctx, int idx) + { + auto& r = ctx.outMatR(idx); + return{ r }; + } +}; +template<> struct ocl_get_out +{ + static cv::Scalar& get(GOCLContext &ctx, int idx) + { + return ctx.outValR(idx); + } +}; +template struct ocl_get_out > +{ + static std::vector& get(GOCLContext &ctx, int idx) { return ctx.outVecR(idx); } +}; +template struct ocl_get_out > +{ + static U& get(GOCLContext &ctx, int idx) { return ctx.outOpaqueR(idx); } +}; + +template +struct OCLCallHelper; + +// FIXME: probably can be simplified with std::apply or analogue. +template +struct OCLCallHelper, std::tuple > +{ + template + struct call_and_postprocess + { + template + static void call(Inputs&&... ins, Outputs&&... outs) + { + //not using a std::forward on outs is deliberate in order to + //cause compilation error, by trying to bind rvalue references to lvalue references + Impl::run(std::forward(ins)..., outs...); + + postprocess_ocl(outs...); + } + }; + + template + static void call_impl(GOCLContext &ctx, detail::Seq, detail::Seq) + { + //TODO: Make sure that OpenCV kernels do not reallocate memory for output parameters + //by comparing it's state (data ptr) before and after the call. + //Convert own::Scalar to cv::Scalar before call kernel and run kernel + //convert cv::Scalar to own::Scalar after call kernel and write back results + call_and_postprocess::get(ctx, IIs))...>::call(ocl_get_in::get(ctx, IIs)..., ocl_get_out::get(ctx, OIs)...); + } + + static void call(GOCLContext &ctx) + { + call_impl(ctx, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } +}; + +} // namespace detail + +template +class GOCLKernelImpl: public cv::detail::OCLCallHelper, + public cv::detail::KernelTag +{ + using P = detail::OCLCallHelper; + +public: + using API = K; + + static cv::gapi::GBackend backend() { return cv::gapi::ocl::backend(); } + static cv::GOCLKernel kernel() { return GOCLKernel(&P::call); } +}; + +#define GAPI_OCL_KERNEL(Name, API) struct Name: public cv::GOCLKernelImpl + +} // namespace cv + +#endif // OPENCV_GAPI_GOCLKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/imgproc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1bb5911b1869de4fdb8d7dd14b5571fbabb6ff1b --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ocl/imgproc.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OCL_IMGPROC_API_HPP +#define OPENCV_GAPI_OCL_IMGPROC_API_HPP + +#include // GAPI_EXPORTS +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace imgproc { +namespace ocl { + + GAPI_EXPORTS GKernelPackage kernels(); + +} // namespace ocl +} // namespace imgproc +} // namespace gapi +} // namespace cv + + +#endif // OPENCV_GAPI_OCL_IMGPROC_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/opencv_includes.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/opencv_includes.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7c2c42d8a2b3f9991b886e76a1303a05374ca494 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/opencv_includes.hpp @@ -0,0 +1,42 @@ +// This file is part of OpenCV project. + +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OPENCV_INCLUDES_HPP +#define OPENCV_GAPI_OPENCV_INCLUDES_HPP + +#if !defined(GAPI_STANDALONE) +# include +# include +# include +# include +#define GAPI_OWN_TYPES_LIST cv::gapi::own::Rect, \ + cv::gapi::own::Size, \ + cv::gapi::own::Point, \ + cv::gapi::own::Point2f, \ + cv::gapi::own::Scalar, \ + cv::gapi::own::Mat +#else // Without OpenCV +# include +# include // cv::gapi::own::Rect/Size/Point +# include // cv::gapi::own::Scalar +# include +// replacement of cv's structures: +namespace cv { + using Rect = gapi::own::Rect; + using Size = gapi::own::Size; + using Point = gapi::own::Point; + using Point2f = gapi::own::Point2f; + using Point3f = gapi::own::Point3f; + using Scalar = gapi::own::Scalar; + using Mat = gapi::own::Mat; +} // namespace cv +#define GAPI_OWN_TYPES_LIST cv::gapi::own::VoidType + +#endif // !defined(GAPI_STANDALONE) + +#endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/operators.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/operators.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6794b44b6e468e47ebd95b5e25c6ae2755fdc9ff --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/operators.hpp @@ -0,0 +1,70 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OPERATORS_HPP +#define OPENCV_GAPI_OPERATORS_HPP + +#include +#include + +namespace cv +{ +GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator+(const cv::GScalar& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator-(const cv::GMat& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator-(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator-(const cv::GScalar& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, float rhs); +GAPI_EXPORTS cv::GMat operator*(float lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator*(const cv::GScalar& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator/(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator&(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator~(const cv::GMat& lhs); + +GAPI_EXPORTS cv::GMat operator&(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator|(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator^(const cv::GScalar& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator&(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GScalar& rhs); + +GAPI_EXPORTS cv::GMat operator>(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator!=(const cv::GMat& lhs, const cv::GMat& rhs); + +GAPI_EXPORTS cv::GMat operator>(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GScalar& rhs); +GAPI_EXPORTS cv::GMat operator!=(const cv::GMat& lhs, const cv::GScalar& rhs); + +GAPI_EXPORTS cv::GMat operator>(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator>=(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator<(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator<=(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator==(const cv::GScalar& lhs, const cv::GMat& rhs); +GAPI_EXPORTS cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs); +} // cv + +#endif // OPENCV_GAPI_OPERATORS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ot.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ot.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b73d7e6ee003dcf9d378add657f0727cdffda53d --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/ot.hpp @@ -0,0 +1,194 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2023 Intel Corporation + +#ifndef OPENCV_GAPI_OT_HPP +#define OPENCV_GAPI_OT_HPP + +#include +#include +#include + +namespace cv { +namespace gapi { +/** + * @brief This namespace contains G-API Operation Types for + * VAS Object Tracking module functionality. + */ +namespace ot { + +/** + * @enum TrackingStatus + * + * Tracking status twin for vas::ot::TrackingStatus + */ +enum TrackingStatus +{ + NEW = 0, /**< The object is newly added. */ + TRACKED, /**< The object is being tracked. */ + LOST /**< The object gets lost now. The object can be tracked again + by specifying detected object manually. */ +}; + +struct GAPI_EXPORTS_W_SIMPLE ObjectTrackerParams +{ + /** + * Maximum number of trackable objects in a frame. + * Valid range: 1 <= max_num_objects. Or it can be -1 if there is no limitation + * of maximum number in X86. KMB/TBH has limitation up to 1024. + * Default value is -1 which means there is no limitation in X86. KMB/TBH is -1 means 200. + */ + GAPI_PROP_RW int32_t max_num_objects = -1; + + /** + * Input color format. Supports 0(BGR), 1(NV12), 2(BGRX) and 4(I420) + */ + GAPI_PROP_RW int32_t input_image_format = 0; + + /** + * Specifies whether tracker to use detection class for keeping id of an object. + * If it is true, new detection will be associated from previous tracking only when + * those two have same class. + * class id of an object is fixed across video frames. + * If it is false, new detection can be associated across different-class objects. + * In this case, the class id of an object may change across video frames depending on the tracker input. + * It is recommended to turn this option off when it is likely that detector confuses the class of object. + * For example, when detector confuses bicycle and motorbike. Turning this option off will increase + * the tracking reliability as tracker will ignore the class label of detector. + * @n + * Default value is true. + */ + GAPI_PROP_RW bool tracking_per_class = true; + + bool operator==(const ObjectTrackerParams& other) const + { + return max_num_objects == other.max_num_objects + && input_image_format == other.input_image_format + && tracking_per_class == other.tracking_per_class; + } +}; + +using GTrackedInfo = std::tuple, cv::GArray, cv::GArray, cv::GArray>; + +G_API_OP(GTrackFromMat, , cv::GArray, float)>, "com.intel.track_from_mat") +{ + static std::tuple outMeta(cv::GMatDesc, cv::GArrayDesc, cv::GArrayDesc, float) + { + return std::make_tuple(cv::empty_array_desc(), cv::empty_array_desc(), + cv::empty_array_desc(), cv::empty_array_desc()); + } +}; + +G_API_OP(GTrackFromFrame, , cv::GArray, float)>, "com.intel.track_from_frame") +{ + static std::tuple outMeta(cv::GFrameDesc, cv::GArrayDesc, cv::GArrayDesc, float) + { + return std::make_tuple(cv::empty_array_desc(), cv::empty_array_desc(), + cv::empty_array_desc(), cv::empty_array_desc()); + } +}; + +/** + * @brief Tracks objects with video frames. + * If a detected object is overlapped enough with one of tracked object, the tracked object's + * informationis updated with the input detected object. + * On the other hand, if a detected object is overlapped with none of tracked objects, + * the detected object is newly added and ObjectTracker starts to track the object. + * In zero term tracking type, ObjectTracker clears tracked objects in case that empty + * list of detected objects is passed in. + * + * @param mat Input frame. + * @param detected_rects Detected objects rectangles in the input frame. + * @param detected_class_labels Detected objects class labels in the input frame. + * @param delta Frame_delta_t Delta time between two consecutive tracking in seconds. + * The valid range is [0.005 ~ 0.5]. + * @return Tracking results of target objects. + * cv::GArray Array of rectangles for tracked objects. + * cv::GArray Array of detected objects labels. + * cv::GArray Array of tracking IDs for objects. + * Numbering sequence starts from 1. + * The value 0 means the tracking ID of this object has + * not been assigned. + * cv::GArray Array of tracking statuses for objects. + */ +GAPI_EXPORTS_W std::tuple, + cv::GArray, + cv::GArray, + cv::GArray> + track(const cv::GMat& mat, + const cv::GArray& detected_rects, + const cv::GArray& detected_class_labels, + float delta); + + +/** + @overload + * @brief Tracks objects with video frames. Overload of track(...) for frame as GFrame. + * + * @param frame Input frame. + * @param detected_rects Detected objects rectangles in the input frame. + * @param detected_class_labels Detected objects class labels in the input frame. + * @param delta Frame_delta_t Delta time between two consecutive tracking in seconds. + * The valid range is [0.005 ~ 0.5]. + * @return Tracking results of target objects. + * @return Tracking results of target objects. + * cv::GArray Array of rectangles for tracked objects. + * cv::GArray Array of detected objects labels. + * cv::GArray Array of tracking IDs for objects. + * Numbering sequence starts from 1. + * The value 0 means the tracking ID of this object has + * not been assigned. + * cv::GArray Array of tracking statuses for objects. + */ +GAPI_EXPORTS_W std::tuple, + cv::GArray, + cv::GArray, + cv::GArray> + track(const cv::GFrame& frame, + const cv::GArray& detected_rects, + const cv::GArray& detected_class_labels, + float delta); +} // namespace ot +} // namespace gapi +} // namespace cv + +// FIXME: move to a separate file? +namespace cv +{ +namespace detail +{ +template<> struct CompileArgTag +{ + static const char* tag() + { + return "cv.gapi.ot.object_tracker_params"; + } +}; +} // namespace detail + +namespace gapi +{ +namespace s11n +{ +namespace detail +{ +template<> struct S11N { + static void serialize(IOStream &os, const cv::gapi::ot::ObjectTrackerParams &p) { + os << p. max_num_objects << p.input_image_format << p.tracking_per_class; + } + static cv::gapi::ot::ObjectTrackerParams deserialize(IIStream &is) { + cv::gapi::ot::ObjectTrackerParams p; + is >> p. max_num_objects >> p.input_image_format >> p.tracking_per_class; + return p; + } +}; +} // namespace detail +} // namespace s11n +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_OT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/assert.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/assert.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ab2fb896f127d77bb31ac0fb4d0d293853be5b40 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/assert.hpp @@ -0,0 +1,60 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_OWN_ASSERT_HPP +#define OPENCV_GAPI_OWN_ASSERT_HPP + +#include + +#define GAPI_DbgAssertNoOp(expr) { \ + constexpr bool _assert_tmp = false && (expr); \ + cv::util::suppress_unused_warning(_assert_tmp); \ +} + +#if !defined(GAPI_STANDALONE) +#include +#define GAPI_Assert CV_Assert + +#if defined _DEBUG || defined CV_STATIC_ANALYSIS +# define GAPI_DbgAssert CV_DbgAssert +#else +# define GAPI_DbgAssert(expr) GAPI_DbgAssertNoOp(expr) +#endif + +#define GAPI_Error(msg) CV_Error(cv::Error::StsError, msg) + +#else +#include +#include +#include + +namespace detail +{ + [[noreturn]] inline void assert_abort(const char* str, int line, const char* file, const char* func) + { + std::stringstream ss; + ss << file << ":" << line << ": Assertion " << str << " in function " << func << " failed\n"; + cv::util::throw_error(std::logic_error(ss.str())); + } +} + +#define GAPI_Assert(expr) \ +{ if (!(expr)) ::detail::assert_abort(#expr, __LINE__, __FILE__, __func__); } + +#ifdef NDEBUG +# define GAPI_DbgAssert(expr) GAPI_DbgAssertNoOp(expr) +#else +# define GAPI_DbgAssert(expr) GAPI_Assert(expr) +#endif + +#define GAPI_Error(msg) { \ + ::detail::assert_abort(msg, __LINE__, __FILE__, __func__); \ +} + +#endif // GAPI_STANDALONE + +#endif // OPENCV_GAPI_OWN_ASSERT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/convert.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/convert.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f587e2478702660889e8342dc5e25c3f55f384d4 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/convert.hpp @@ -0,0 +1,55 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OWN_CONVERT_HPP +#define OPENCV_GAPI_OWN_CONVERT_HPP + +#if !defined(GAPI_STANDALONE) + +#include +#include + +namespace cv +{ + template + std::vector to_own(const cv::MatSize &sz) { + std::vector result(sz.dims()); + for (int i = 0; i < sz.dims(); i++) { + // Note: cv::MatSize is not iterable + result[i] = static_cast(sz[i]); + } + return result; + } + + cv::gapi::own::Mat to_own(Mat&&) = delete; + + inline cv::gapi::own::Mat to_own(Mat const& m) { + return (m.dims == 2) + ? cv::gapi::own::Mat{m.rows, m.cols, m.type(), m.data, m.step} + : cv::gapi::own::Mat{to_own(m.size), m.type(), m.data}; + } + +namespace gapi +{ +namespace own +{ + + inline cv::Mat to_ocv(Mat const& m) { + return m.dims.empty() + ? cv::Mat{m.rows, m.cols, m.type(), m.data, m.step} + : cv::Mat{m.dims, m.type(), m.data}; + } + + cv::Mat to_ocv(Mat&&) = delete; + +} // namespace own +} // namespace gapi +} // namespace cv + +#endif // !defined(GAPI_STANDALONE) + +#endif // OPENCV_GAPI_OWN_CONVERT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/cvdefs.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/cvdefs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d3bef98e9805b4a7b0d56b83a180b5c8e0658503 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/cvdefs.hpp @@ -0,0 +1,166 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_CV_DEFS_HPP +#define OPENCV_GAPI_CV_DEFS_HPP + +#if defined(GAPI_STANDALONE) +// Simulate OpenCV definitions taken from various +// OpenCV interface headers if G-API is built in a +// standalone mode. + +// interface.h: + +typedef unsigned char uchar; +typedef char schar; + +typedef unsigned short ushort; + +#define CV_USRTYPE1 (void)"CV_USRTYPE1 support has been dropped in OpenCV 4.0" + +#define CV_CN_MAX 512 +#define CV_CN_SHIFT 3 +#define CV_DEPTH_MAX (1 << CV_CN_SHIFT) + +#define CV_8U 0 +#define CV_8S 1 +#define CV_16U 2 +#define CV_16S 3 +#define CV_32S 4 +#define CV_32F 5 +#define CV_64F 6 +#define CV_16F 7 + +#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1) +#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK) + +#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT)) +#define CV_MAKE_TYPE CV_MAKETYPE + +#define CV_8UC1 CV_MAKETYPE(CV_8U,1) +#define CV_8UC2 CV_MAKETYPE(CV_8U,2) +#define CV_8UC3 CV_MAKETYPE(CV_8U,3) +#define CV_8UC4 CV_MAKETYPE(CV_8U,4) +#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n)) + +#define CV_8SC1 CV_MAKETYPE(CV_8S,1) +#define CV_8SC2 CV_MAKETYPE(CV_8S,2) +#define CV_8SC3 CV_MAKETYPE(CV_8S,3) +#define CV_8SC4 CV_MAKETYPE(CV_8S,4) +#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n)) + +#define CV_16UC1 CV_MAKETYPE(CV_16U,1) +#define CV_16UC2 CV_MAKETYPE(CV_16U,2) +#define CV_16UC3 CV_MAKETYPE(CV_16U,3) +#define CV_16UC4 CV_MAKETYPE(CV_16U,4) +#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n)) + +#define CV_16SC1 CV_MAKETYPE(CV_16S,1) +#define CV_16SC2 CV_MAKETYPE(CV_16S,2) +#define CV_16SC3 CV_MAKETYPE(CV_16S,3) +#define CV_16SC4 CV_MAKETYPE(CV_16S,4) +#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n)) + +#define CV_32SC1 CV_MAKETYPE(CV_32S,1) +#define CV_32SC2 CV_MAKETYPE(CV_32S,2) +#define CV_32SC3 CV_MAKETYPE(CV_32S,3) +#define CV_32SC4 CV_MAKETYPE(CV_32S,4) +#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n)) + +#define CV_16FC1 CV_MAKETYPE(CV_16F,1) +#define CV_16FC2 CV_MAKETYPE(CV_16F,2) +#define CV_16FC3 CV_MAKETYPE(CV_16F,3) +#define CV_16FC4 CV_MAKETYPE(CV_16F,4) +#define CV_16FC(n) CV_MAKETYPE(CV_16F,(n)) + +#define CV_32FC1 CV_MAKETYPE(CV_32F,1) +#define CV_32FC2 CV_MAKETYPE(CV_32F,2) +#define CV_32FC3 CV_MAKETYPE(CV_32F,3) +#define CV_32FC4 CV_MAKETYPE(CV_32F,4) +#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n)) + +#define CV_64FC1 CV_MAKETYPE(CV_64F,1) +#define CV_64FC2 CV_MAKETYPE(CV_64F,2) +#define CV_64FC3 CV_MAKETYPE(CV_64F,3) +#define CV_64FC4 CV_MAKETYPE(CV_64F,4) +#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n)) + +// cvdef.h: + +#ifndef CV_ALWAYS_INLINE +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define CV_ALWAYS_INLINE inline __attribute__((always_inline)) +# elif defined(_MSC_VER) +# define CV_ALWAYS_INLINE __forceinline +# else +# define CV_ALWAYS_INLINE inline +# endif +#endif + +#define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT) +#define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) +#define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1) +#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK) +#define CV_MAT_CONT_FLAG_SHIFT 14 +#define CV_MAT_CONT_FLAG (1 << CV_MAT_CONT_FLAG_SHIFT) +#define CV_IS_MAT_CONT(flags) ((flags) & CV_MAT_CONT_FLAG) +#define CV_IS_CONT_MAT CV_IS_MAT_CONT +#define CV_SUBMAT_FLAG_SHIFT 15 +#define CV_SUBMAT_FLAG (1 << CV_SUBMAT_FLAG_SHIFT) +#define CV_IS_SUBMAT(flags) ((flags) & CV_MAT_SUBMAT_FLAG) + +//** Size of each channel item, +// 0x8442211 = 1000 0100 0100 0010 0010 0001 0001 ~ array of sizeof(arr_type_elem) */ +#define CV_ELEM_SIZE1(type) \ + ((((sizeof(size_t)<<28)|0x8442211) >> CV_MAT_DEPTH(type)*4) & 15) + +#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK) + +/** 0x3a50 = 11 10 10 01 01 00 00 ~ array of log2(sizeof(arr_type_elem)) */ +#define CV_ELEM_SIZE(type) \ + (CV_MAT_CN(type) << ((((sizeof(size_t)/4+1)*16384|0x3a50) >> CV_MAT_DEPTH(type)*2) & 3)) + +#ifndef CV_OVERRIDE +# define CV_OVERRIDE override +#endif + +// base.h: +namespace cv +{ +enum BorderTypes { + BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i` + BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh` + BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb` + BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg` + BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba` + BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno` + + BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101 + BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101 + BORDER_ISOLATED = 16 //!< do not look outside of ROI +}; +// imgproc.hpp: +enum InterpolationFlags{ + INTER_NEAREST = 0, + INTER_LINEAR = 1, + INTER_CUBIC = 2, + INTER_AREA = 3, + INTER_LANCZOS4 = 4, + INTER_LINEAR_EXACT = 5, + INTER_MAX = 7, +}; +} // namespace cv + +static inline int cvFloor( double value ) +{ + int i = (int)value; + return i - (i > value); +} + +#endif // defined(GAPI_STANDALONE) + +#endif // OPENCV_GAPI_CV_DEFS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/exports.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/exports.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c36f4003d0fbda2444ec2aac321fb622d2e6cdc2 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/exports.hpp @@ -0,0 +1,42 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OWN_TYPES_HPP +#define OPENCV_GAPI_OWN_TYPES_HPP + +# if defined(__OPENCV_BUILD) +# include +# define GAPI_EXPORTS CV_EXPORTS + /* special informative macros for wrapper generators */ +# define GAPI_PROP CV_PROP +# define GAPI_PROP_RW CV_PROP_RW +# define GAPI_WRAP CV_WRAP +# define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE +# define GAPI_EXPORTS_W CV_EXPORTS_W +# else +# define GAPI_PROP +# define GAPI_PROP_RW +# define GAPI_WRAP +# define GAPI_EXPORTS +# define GAPI_EXPORTS_W_SIMPLE +# define GAPI_EXPORTS_W + +#if 0 // Note: the following version currently is not needed for non-OpenCV build +# if defined _WIN32 +# define GAPI_EXPORTS __declspec(dllexport) +# elif defined __GNUC__ && __GNUC__ >= 4 +# define GAPI_EXPORTS __attribute__ ((visibility ("default"))) +# endif + +# ifndef GAPI_EXPORTS +# define GAPI_EXPORTS +# endif +#endif + +# endif + +#endif // OPENCV_GAPI_OWN_TYPES_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/mat.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/mat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ce9c0bf3623839861ff783c2ae2767ba7d2d3d06 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/mat.hpp @@ -0,0 +1,354 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OWN_MAT_HPP +#define OPENCV_GAPI_OWN_MAT_HPP + +#include +#include +#include +#include +#include + +#include //std::shared_ptr +#include //std::memcpy +#include //std::accumulate +#include +#include + +namespace cv { namespace gapi { namespace own { + namespace detail { + template + void assign_row(void* ptr, int cols, Scalar const& s) + { + auto p = static_cast(ptr); + for (int c = 0; c < cols; c++) + { + for (int ch = 0; ch < channels; ch++) + { + p[c * channels + ch] = saturate(s[ch], roundd); + } + } + } + + inline size_t default_step(int type, int cols) + { + return CV_ELEM_SIZE(type) * cols; + } + //Matrix header, i.e. fields that are unique to each Mat object. + //Devoted class is needed to implement custom behavior on move (erasing state of moved from object) + struct MatHeader{ + enum { AUTO_STEP = 0}; + enum { TYPE_MASK = 0x00000FFF }; + + MatHeader() = default; + + MatHeader(int _rows, int _cols, int type, void* _data, size_t _step) + : flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step) + {} + + MatHeader(const std::vector &_dims, int type, void* _data) + : flags((type & TYPE_MASK)), data((uchar*)_data), step(0), dims(_dims) + {} + + MatHeader(const MatHeader& ) = default; + MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here + { + MatHeader empty; //give it a name to call copy(not move) assignment below + src = empty; + } + MatHeader& operator=(const MatHeader& ) = default; + MatHeader& operator=(MatHeader&& src) + { + *this = src; //calling a copy assignment here, not move one + MatHeader empty; //give it a name to call copy(not move) assignment below + src = empty; + return *this; + } + /*! includes several bit-fields: + - depth + - number of channels + */ + int flags = 0; + + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows = 0, cols = 0; + //! pointer to the data + uchar* data = nullptr; + size_t step = 0; + //! dimensions (ND-case) + std::vector dims; + }; + } // namespace detail + //concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required) + class Mat : public detail::MatHeader{ + public: + + Mat() = default; + + /** @overload + @param _rows Number of rows in a 2D array. + @param _cols Number of columns in a 2D array. + @param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param _data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param _step Number of bytes each matrix row occupies. The value should include the padding bytes at + the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed + and the actual step is calculated as cols*elemSize(). See Mat::elemSize. + */ + Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP) + : MatHeader (_rows, _cols, _type, _data, _step) + {} + + Mat(const std::vector &_dims, int _type, void* _data) + : MatHeader (_dims, _type, _data) + {} + + Mat(std::vector &&_dims, int _type, void* _data) + : MatHeader (std::move(_dims), _type, _data) + {} + + Mat(Mat const& src, const Rect& roi ) + : Mat(src) + { + rows = roi.height; + cols = roi.width; + data = ptr(roi.y, roi.x); + } + + Mat(Mat const& ) = default; + Mat(Mat&& ) = default; + + Mat& operator=(Mat const& ) = default; + Mat& operator=(Mat&& ) = default; + + /** @brief Sets all or some of the array elements to the specified value. + @param s Assigned scalar converted to the actual array type. + */ + Mat& operator = (const Scalar& s) + { + constexpr unsigned max_channels = 4; //Scalar can't fit more than 4 + using func_p_t = void (*)(void*, int, Scalar const&); + using detail::assign_row; + #define TABLE_ENTRY(type) {assign_row, assign_row, assign_row, assign_row} + static constexpr func_p_t func_tbl[][max_channels] = { + TABLE_ENTRY(uchar), + TABLE_ENTRY(schar), + TABLE_ENTRY(ushort), + TABLE_ENTRY(short), + TABLE_ENTRY(int), + TABLE_ENTRY(float), + TABLE_ENTRY(double) + }; + #undef TABLE_ENTRY + + static_assert(CV_8U == 0 && CV_8S == 1 && CV_16U == 2 && CV_16S == 3 + && CV_32S == 4 && CV_32F == 5 && CV_64F == 6, + "OCV type ids used as indexes to array, thus exact numbers are important!" + ); + + const auto depth = static_cast(this->depth()); + GAPI_Assert(depth < sizeof(func_tbl)/sizeof(func_tbl[0])); + + if (dims.empty()) + { + const auto channels = static_cast(this->channels()); + GAPI_Assert(channels <= max_channels); + + auto* f = func_tbl[depth][channels - 1]; + for (int r = 0; r < rows; ++r) + { + (*f)(static_cast(ptr(r)), cols, s ); + } + } + else + { + auto* f = func_tbl[depth][0]; + // FIXME: better to refactor assign_row to use std::size_t by default + (*f)(static_cast(data), static_cast(total()), s); + } + return *this; + } + + /** @brief Returns the matrix element size in bytes. + + The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 , + the method returns 3\*sizeof(short) or 6. + */ + size_t elemSize() const + { + return CV_ELEM_SIZE(type()); + } + /** @brief Returns the type of a matrix element. + + The method returns a matrix element type. This is an identifier compatible with the CvMat type + system, like CV_16SC3 or 16-bit signed 3-channel array, and so on. + */ + int type() const {return CV_MAT_TYPE(flags);} + + /** @brief Returns the depth of a matrix element. + + The method returns the identifier of the matrix element depth (the type of each individual channel). + For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of + matrix types contains the following values: + - CV_8U - 8-bit unsigned integers ( 0..255 ) + - CV_8S - 8-bit signed integers ( -128..127 ) + - CV_16U - 16-bit unsigned integers ( 0..65535 ) + - CV_16S - 16-bit signed integers ( -32768..32767 ) + - CV_32S - 32-bit signed integers ( -2147483648..2147483647 ) + - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN ) + - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN ) + */ + int depth() const {return CV_MAT_DEPTH(flags);} + + /** @brief Returns the number of matrix channels. + + The method returns the number of matrix channels. + If matrix is N-dimensional, -1 is returned. + */ + int channels() const {return dims.empty() ? CV_MAT_CN(flags) : -1;} + + /** + @param _rows New number of rows. + @param _cols New number of columns. + @param _type New matrix type. + */ + void create(int _rows, int _cols, int _type) + { + create(Size{_cols, _rows}, _type); + } + /** @overload + @param _size Alternative new matrix size specification: Size(cols, rows) + @param _type New matrix type. + */ + void create(Size _size, int _type) + { + GAPI_Assert(_size.height >= 0 && _size.width >= 0); + if (_size != Size{cols, rows} ) + { + Mat tmp{_size.height, _size.width, _type, nullptr}; + tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;}); + tmp.data = tmp.memory.get(); + + *this = std::move(tmp); + } + } + + void create(const std::vector &_dims, int _type) + { + // FIXME: make a proper reallocation-on-demands + // WARNING: no tensor views, so no strides + Mat tmp{_dims, _type, nullptr}; + // FIXME: this accumulate duplicates a lot + const auto sz = std::accumulate(_dims.begin(), _dims.end(), 1, std::multiplies()); + tmp.memory.reset(new uchar[CV_ELEM_SIZE(_type)*sz], [](uchar * p){delete[] p;}); + tmp.data = tmp.memory.get(); + *this = std::move(tmp); + } + + /** @brief Creates a full copy of the matrix and the underlying data. + + The method creates a full copy of the matrix. The original step[] is not taken into account. + So, the copy has a continuous buffer occupying total() * elemSize() bytes. + */ + Mat clone() const + { + Mat m; + copyTo(m); + return m; + } + + /** @brief Copies the matrix to another one. + + The method copies the matrix data to another matrix. Before copying the data, the method invokes : + @code + m.create(this->size(), this->type()); + @endcode + so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the + function does not handle the case of a partial overlap between the source and the destination + matrices. + */ + void copyTo(Mat& dst) const + { + if (dims.empty()) + { + dst.create(rows, cols, type()); + for (int r = 0; r < rows; ++r) + { + std::copy_n(ptr(r), detail::default_step(type(),cols), dst.ptr(r)); + } + } + else + { + dst.create(dims, depth()); + std::copy_n(data, total()*elemSize(), data); + } + } + + /** @brief Returns true if the array has no elements. + + The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and + resize() methods `M.total() == 0` does not imply that `M.data == NULL`. + */ + bool empty() const + { + return data == 0 || total() == 0; + } + + /** @brief Returns the total number of array elements. + + The method returns the number of array elements (a number of pixels if the array represents an + image). + */ + size_t total() const + { + return dims.empty() + ? (static_cast(rows) * cols) + : std::accumulate(dims.begin(), dims.end(), static_cast(1), std::multiplies()); + } + + /** @overload + @param roi Extracted submatrix specified as a rectangle. + */ + Mat operator()( const Rect& roi ) const + { + return Mat{*this, roi}; + } + + + /** @brief Returns a pointer to the specified matrix row. + + The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in + Mat::isContinuous to know how to use these methods. + @param row Index along the dimension 0 + @param col Index along the dimension 1 + */ + uchar* ptr(int row, int col = 0) + { + return const_cast(const_cast(this)->ptr(row,col)); + } + /** @overload */ + const uchar* ptr(int row, int col = 0) const + { + return data + step * row + CV_ELEM_SIZE(type()) * col; + } + + + private: + //actual memory allocated for storage, or nullptr if object is non owning view to over memory + std::shared_ptr memory; + }; + +} //namespace own +} //namespace gapi +} //namespace cv + +#endif /* OPENCV_GAPI_OWN_MAT_HPP */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/saturate.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/saturate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..74eaecf57e69da31200b5d165eaaea8df8f263fd --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/saturate.hpp @@ -0,0 +1,83 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_OWN_SATURATE_HPP +#define OPENCV_GAPI_OWN_SATURATE_HPP + +#include + +#include + +#include +#include + +namespace cv { namespace gapi { namespace own { +//----------------------------- +// +// Numeric cast with saturation +// +//----------------------------- + +template::value && + std::is_integral::value && + std::is_integral::value> > +static CV_ALWAYS_INLINE DST saturate(SRC x) +{ + if (sizeof(DST) > sizeof(SRC)) + return static_cast(x); + + // compiler must recognize this saturation, + // so compile saturate(a + b) with adds + // instruction (e.g.: _mm_adds_epi16 if x86) + return x < std::numeric_limits::min()? + std::numeric_limits::min(): + x > std::numeric_limits::max()? + std::numeric_limits::max(): + static_cast(x); +} +template +static CV_ALWAYS_INLINE T saturate(T x) +{ + return x; +} + +template::value, bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R) +{ + return static_cast(x); +} +template::value && + std::is_integral::value , bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R) +{ + return saturate(x); +} +// Note, that OpenCV rounds differently: +// - like std::round() for add, subtract +// - like std::rint() for multiply, divide +template::value && + std::is_floating_point::value, bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R round) +{ + int ix = static_cast(round(x)); + return saturate(ix); +} + +// explicit suffix 'd' for double type +inline double ceild(double x) { return ceil(x); } +inline double floord(double x) { return floor(x); } +inline double roundd(double x) { return round(x); } +inline double rintd(double x) { return rint(x); } + +} //namespace own +} //namespace gapi +} //namespace cv +#endif /* OPENCV_GAPI_OWN_SATURATE_HPP */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/scalar.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/scalar.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3b107befccaa6e4d34b1fc1aac72af157a25b9ea --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/scalar.hpp @@ -0,0 +1,47 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_GAPI_OWN_SCALAR_HPP +#define OPENCV_GAPI_GAPI_OWN_SCALAR_HPP + +#include + +namespace cv +{ +namespace gapi +{ +namespace own +{ + +class GAPI_EXPORTS Scalar +{ +public: + Scalar() = default; + explicit Scalar(double v0) { val[0] = v0; } + Scalar(double v0, double v1, double v2 = 0, double v3 = 0) + : val{v0, v1, v2, v3} + { + } + + const double& operator[](int i) const { return val[i]; } + double& operator[](int i) { return val[i]; } + + static Scalar all(double v0) { return Scalar(v0, v0, v0, v0); } + + double val[4] = {0}; +}; + +inline bool operator==(const Scalar& lhs, const Scalar& rhs) +{ + return std::equal(std::begin(lhs.val), std::end(lhs.val), std::begin(rhs.val)); +} + +} // namespace own +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_GAPI_OWN_SCALAR_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/types.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/types.hpp new file mode 100644 index 0000000000000000000000000000000000000000..211b5c85ff12911831680e47f9709abe8dd5259a --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/own/types.hpp @@ -0,0 +1,162 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_TYPES_HPP +#define OPENCV_GAPI_TYPES_HPP + +#include // std::max, std::min +#include + +namespace cv +{ +namespace gapi +{ + +/** + * @brief This namespace contains G-API own data structures used in + * its standalone mode build. + */ +namespace own +{ + +class Point +{ +public: + Point() = default; + Point(int _x, int _y) : x(_x), y(_y) {} + + int x = 0; + int y = 0; +}; + +class Point2f +{ +public: + Point2f() = default; + Point2f(float _x, float _y) : x(_x), y(_y) {} + + float x = 0.f; + float y = 0.f; +}; + +class Point3f +{ +public: + Point3f() = default; + Point3f(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + + float x = 0.f; + float y = 0.f; + float z = 0.f; +}; + +class Rect +{ +public: + Rect() = default; + Rect(int _x, int _y, int _width, int _height) : x(_x), y(_y), width(_width), height(_height) {} +#if !defined(GAPI_STANDALONE) + Rect(const cv::Rect& other) : x(other.x), y(other.y), width(other.width), height(other.height) {} + inline Rect& operator=(const cv::Rect& other) + { + x = other.x; + y = other.x; + width = other.width; + height = other.height; + return *this; + } +#endif // !defined(GAPI_STANDALONE) + + int x = 0; //!< x coordinate of the top-left corner + int y = 0; //!< y coordinate of the top-left corner + int width = 0; //!< width of the rectangle + int height = 0; //!< height of the rectangle +}; + +inline bool operator==(const Rect& lhs, const Rect& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline bool operator!=(const Rect& lhs, const Rect& rhs) +{ + return !(lhs == rhs); +} + +inline Rect& operator&=(Rect& lhs, const Rect& rhs) +{ + int x1 = std::max(lhs.x, rhs.x); + int y1 = std::max(lhs.y, rhs.y); + lhs.width = std::min(lhs.x + lhs.width, rhs.x + rhs.width) - x1; + lhs.height = std::min(lhs.y + lhs.height, rhs.y + rhs.height) - y1; + lhs.x = x1; + lhs.y = y1; + if( lhs.width <= 0 || lhs.height <= 0 ) + lhs = Rect(); + return lhs; +} + +inline Rect operator&(const Rect& lhs, const Rect& rhs) +{ + Rect result = lhs; + return result &= rhs; +} + +inline std::ostream& operator<<(std::ostream& o, const Rect& rect) +{ + return o << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]"; +} + +class Size +{ +public: + Size() = default; + Size(int _width, int _height) : width(_width), height(_height) {} +#if !defined(GAPI_STANDALONE) + Size(const cv::Size& other) : width(other.width), height(other.height) {} + inline Size& operator=(const cv::Size& rhs) + { + width = rhs.width; + height = rhs.height; + return *this; + } +#endif // !defined(GAPI_STANDALONE) + + int width = 0; + int height = 0; +}; + +inline Size& operator+=(Size& lhs, const Size& rhs) +{ + lhs.width += rhs.width; + lhs.height += rhs.height; + return lhs; +} + +inline bool operator==(const Size& lhs, const Size& rhs) +{ + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline bool operator!=(const Size& lhs, const Size& rhs) +{ + return !(lhs == rhs); +} + + +inline std::ostream& operator<<(std::ostream& o, const Size& s) +{ + o << "[" << s.width << " x " << s.height << "]"; + return o; +} + +struct VoidType {}; +} // namespace own +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_TYPES_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/core.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/core.hpp new file mode 100644 index 0000000000000000000000000000000000000000..20e8812b3abc60b9e9207eb50a6764a252e2d378 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/core.hpp @@ -0,0 +1,20 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + + +#ifndef OPENCV_GAPI_PLAIDML_CORE_HPP +#define OPENCV_GAPI_PLAIDML_CORE_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { namespace gapi { namespace core { namespace plaidml { + +GAPI_EXPORTS cv::GKernelPackage kernels(); + +}}}} + +#endif // OPENCV_GAPI_PLAIDML_CORE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/gplaidmlkernel.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/gplaidmlkernel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e22ecc7211f2f1ec3e0ffd2a8e90858430689b58 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/gplaidmlkernel.hpp @@ -0,0 +1,140 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation +// + + +#ifndef OPENCV_GAPI_GPLAIDMLKERNEL_HPP +#define OPENCV_GAPI_GPLAIDMLKERNEL_HPP + +#include +#include + +namespace plaidml +{ +namespace edsl +{ + class Tensor; +} // namespace edsl +} // namespace plaidml + +namespace cv +{ +namespace gapi +{ +namespace plaidml +{ + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +} // namespace plaidml +} // namespace gapi + +struct GPlaidMLContext +{ + // Generic accessor API + template + const T& inArg(int input) { return m_args.at(input).get(); } + + // Syntax sugar + const plaidml::edsl::Tensor& inTensor(int input) + { + return inArg(input); + } + + plaidml::edsl::Tensor& outTensor(int output) + { + return *(m_results.at(output).get()); + } + + std::vector m_args; + std::unordered_map m_results; +}; + +class GAPI_EXPORTS GPlaidMLKernel +{ +public: + using F = std::function; + + GPlaidMLKernel() = default; + explicit GPlaidMLKernel(const F& f) : m_f(f) {} + + void apply(GPlaidMLContext &ctx) const + { + GAPI_Assert(m_f); + m_f(ctx); + } + +protected: + F m_f; +}; + + +namespace detail +{ + +template struct plaidml_get_in; +template<> struct plaidml_get_in +{ + static const plaidml::edsl::Tensor& get(GPlaidMLContext& ctx, int idx) + { + return ctx.inTensor(idx); + } +}; + +template struct plaidml_get_in +{ + static T get(GPlaidMLContext &ctx, int idx) { return ctx.inArg(idx); } +}; + +template struct plaidml_get_out; +template<> struct plaidml_get_out +{ + static plaidml::edsl::Tensor& get(GPlaidMLContext& ctx, int idx) + { + return ctx.outTensor(idx); + } +}; + +template +struct PlaidMLCallHelper; + +template +struct PlaidMLCallHelper, std::tuple > +{ + template + static void call_impl(GPlaidMLContext &ctx, detail::Seq, detail::Seq) + { + Impl::run(plaidml_get_in::get(ctx, IIs)..., plaidml_get_out::get(ctx, OIs)...); + } + + static void call(GPlaidMLContext& ctx) + { + call_impl(ctx, + typename detail::MkSeq::type(), + typename detail::MkSeq::type()); + } +}; + +} // namespace detail + +template +class GPlaidMLKernelImpl: public cv::detail::PlaidMLCallHelper, + public cv::detail::KernelTag +{ + using P = detail::PlaidMLCallHelper; + +public: + using API = K; + + static cv::gapi::GBackend backend() { return cv::gapi::plaidml::backend(); } + static cv::GPlaidMLKernel kernel() { return GPlaidMLKernel(&P::call); } +}; + +#define GAPI_PLAIDML_KERNEL(Name, API) struct Name: public cv::GPlaidMLKernelImpl + +} // namespace cv + +#endif // OPENCV_GAPI_GPLAIDMLKERNEL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/plaidml.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/plaidml.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3207a8cb2e446294b56d07e4a0337e88e8aca81d --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/plaidml/plaidml.hpp @@ -0,0 +1,53 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + + +#ifndef OPENCV_GAPI_PLAIDML_PLAIDML_HPP +#define OPENCV_GAPI_PLAIDML_PLAIDML_HPP + +#include +#include // CompileArgTag + +namespace cv +{ +namespace gapi +{ + +/** + * @brief This namespace contains G-API PlaidML backend functions, + * structures, and symbols. + */ +namespace plaidml +{ + +/** \addtogroup gapi_compile_args + * @{ + */ +/** + * @brief This structure represents the basic parameters for the experimental + * PlaidML backend. + */ +struct config +{ + std::string dev_id; //!< Device ID. Refer to PlaidML documentation for details. + std::string trg_id; //!< Target ID. Refer to PlaidML documentation for details. +}; +/** @} gapi_compile_args */ + +} // namespace plaidml +} // namespace gapi + +namespace detail +{ + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.plaidml.config"; } + }; +} // namespace detail + +} // namespace cv + +#endif // OPENCV_GAPI_PLAIDML_PLAIDML_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/python/python.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/python/python.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1857a938d5bbafd9536dca57d78cda7dc8401526 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/python/python.hpp @@ -0,0 +1,71 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + + +#ifndef OPENCV_GAPI_PYTHON_API_HPP +#define OPENCV_GAPI_PYTHON_API_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { +namespace gapi { + +/** + * @brief This namespace contains G-API Python backend functions, + * structures, and symbols. + * + * This functionality is required to enable G-API custom operations + * and kernels when using G-API from Python, no need to use it in the + * C++ form. + */ +namespace python { + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +struct GPythonContext +{ + const cv::GArgs &ins; + const cv::GMetaArgs &in_metas; + const cv::GTypesInfo &out_info; + + cv::optional m_state; +}; + +using Impl = std::function; +using Setup = std::function; + +class GAPI_EXPORTS GPythonKernel +{ +public: + GPythonKernel() = default; + GPythonKernel(Impl run, Setup setup); + + Impl run; + Setup setup = nullptr; + bool is_stateful = false; +}; + +class GAPI_EXPORTS GPythonFunctor : public cv::gapi::GFunctor +{ +public: + using Meta = cv::GKernel::M; + + GPythonFunctor(const char* id, const Meta& meta, const Impl& impl, + const Setup& setup = nullptr); + + GKernelImpl impl() const override; + gapi::GBackend backend() const override; + +private: + GKernelImpl impl_; +}; + +} // namespace python +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_PYTHON_API_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render.hpp new file mode 100644 index 0000000000000000000000000000000000000000..52e55b0d800f7ff76c7308b219ebfd5c86163800 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render.hpp @@ -0,0 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_RENDER_ROOT_HPP +#define OPENCV_GAPI_RENDER_ROOT_HPP + +// This file is just a shortcut to render/render.hpp + +#include + +#endif // OPENCV_GAPI_RENDER_ROOT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8d93a6efc0283f78d8c1e6614d13c42a27f1f858 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render.hpp @@ -0,0 +1,196 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2020 Intel Corporation + + +#ifndef OPENCV_GAPI_RENDER_HPP +#define OPENCV_GAPI_RENDER_HPP + +#include + +#include + +/** \defgroup gapi_draw G-API Drawing and composition functionality + * @{ + * + * @brief Functions for in-graph drawing. + * + * @note This is a Work in Progress functionality and APIs may + * change in the future releases. + * + * G-API can do some in-graph drawing with a generic operations and a + * set of [rendering primitives](@ref gapi_draw_prims). + * In contrast with traditional OpenCV, in G-API user need to form a + * *rendering list* of primitives to draw. This list can be built + * manually or generated within a graph. This list is passed to + * [special operations or functions](@ref gapi_draw_api) where all + * primitives are interpreted and applied to the image. + * + * For example, in a complex pipeline a list of detected objects + * can be translated in-graph to a list of cv::gapi::wip::draw::Rect + * primitives to highlight those with bounding boxes, or a list of + * detected faces can be translated in-graph to a list of + * cv::gapi::wip::draw::Mosaic primitives to hide sensitive content + * or protect privacy. + * + * Like any other operations, rendering in G-API can be reimplemented + * by different backends. Currently only an OpenCV-based backend is + * available. + * + * In addition to the graph-level operations, there are also regular + * (immediate) OpenCV-like functions are available -- see + * cv::gapi::wip::draw::render(). These functions are just wrappers + * over regular G-API and build the rendering graphs on the fly, so + * take compilation arguments as parameters. + * + * Currently this API is more machine-oriented than human-oriented. + * The main purpose is to translate a set of domain-specific objects + * to a list of primitives to draw. For example, in order to generate + * a picture like this: + * + * ![](modules/gapi/doc/pics/render_example.png) + * + * Rendering list needs to be generated as follows: + * + * @include modules/gapi/samples/draw_example.cpp + * + * @defgroup gapi_draw_prims Drawing primitives + * @defgroup gapi_draw_api Drawing operations and functions + * @} + */ + +namespace cv +{ +namespace gapi +{ +namespace wip +{ +namespace draw +{ + +using GMat2 = std::tuple; +using GMatDesc2 = std::tuple; + +//! @addtogroup gapi_draw_api +//! @{ +/** @brief The function renders on the input image passed drawing primitivies + +@param bgr input image: 8-bit unsigned 3-channel image @ref CV_8UC3. +@param prims vector of drawing primitivies +@param args graph compile time parameters +*/ +void GAPI_EXPORTS_W render(cv::Mat& bgr, + const Prims& prims, + cv::GCompileArgs&& args = {}); + +/** @brief The function renders on two NV12 planes passed drawing primitivies + +@param y_plane input image: 8-bit unsigned 1-channel image @ref CV_8UC1. +@param uv_plane input image: 8-bit unsigned 2-channel image @ref CV_8UC2. +@param prims vector of drawing primitivies +@param args graph compile time parameters +*/ +void GAPI_EXPORTS_W render(cv::Mat& y_plane, + cv::Mat& uv_plane, + const Prims& prims, + cv::GCompileArgs&& args = {}); + +/** @brief The function renders on the input media frame passed drawing primitivies + +@param frame input Media Frame : @ref cv::MediaFrame. +@param prims vector of drawing primitivies +@param args graph compile time parameters +*/ +void GAPI_EXPORTS render(cv::MediaFrame& frame, + const Prims& prims, + cv::GCompileArgs&& args = {}); + + +G_TYPED_KERNEL_M(GRenderNV12, )>, "org.opencv.render.nv12") +{ + static GMatDesc2 outMeta(GMatDesc y_plane, GMatDesc uv_plane, GArrayDesc) + { + return std::make_tuple(y_plane, uv_plane); + } +}; + +G_TYPED_KERNEL(GRenderBGR, )>, "org.opencv.render.bgr") +{ + static GMatDesc outMeta(GMatDesc bgr, GArrayDesc) + { + return bgr; + } +}; + +G_TYPED_KERNEL(GRenderFrame, )>, "org.opencv.render.frame") +{ + static GFrameDesc outMeta(GFrameDesc desc, GArrayDesc) + { + return desc; + } +}; + +/** @brief Renders on 3 channels input + +Output image must be 8-bit unsigned planar 3-channel image + +@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3 +@param prims draw primitives +*/ +GAPI_EXPORTS_W GMat render3ch(const GMat& src, const GArray& prims); + +/** @brief Renders on two planes + +Output y image must be 8-bit unsigned planar 1-channel image @ref CV_8UC1 +uv image must be 8-bit unsigned planar 2-channel image @ref CV_8UC2 + +@param y input image: 8-bit unsigned 1-channel image @ref CV_8UC1 +@param uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2 +@param prims draw primitives +*/ +GAPI_EXPORTS_W GMat2 renderNV12(const GMat& y, + const GMat& uv, + const GArray& prims); + +/** @brief Renders Media Frame + +Output media frame frame cv::MediaFrame + +@param m_frame input image: cv::MediaFrame @ref cv::MediaFrame +@param prims draw primitives +*/ +GAPI_EXPORTS GFrame renderFrame(const GFrame& m_frame, + const GArray& prims); + +//! @} gapi_draw_api + +} // namespace draw +} // namespace wip + +/** + * @brief This namespace contains G-API CPU rendering backend functions, + * structures, and symbols. See @ref gapi_draw for details. + */ +namespace render +{ +namespace ocv +{ + GAPI_EXPORTS_W cv::GKernelPackage kernels(); + +} // namespace ocv +} // namespace render +} // namespace gapi + +namespace detail +{ + template<> struct CompileArgTag + { + static const char* tag() { return "gapi.freetype_font"; } + }; +} // namespace detail + +} // namespace cv + +#endif // OPENCV_GAPI_RENDER_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render_types.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render_types.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6d70e3a877ddf7bd011305476c82ed7f76606b1c --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/render/render_types.hpp @@ -0,0 +1,359 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + + +#ifndef OPENCV_GAPI_RENDER_TYPES_HPP +#define OPENCV_GAPI_RENDER_TYPES_HPP + +#include +#include + +#include +#include +#include + +namespace cv +{ +namespace gapi +{ +namespace wip +{ +namespace draw +{ + +/** + * @brief This structure specifies which FreeType font to use by FText primitives. + */ +struct freetype_font +{ + /*@{*/ + std::string path; //!< The path to the font file (.ttf) + /*@{*/ +}; + +//! @addtogroup gapi_draw_prims +//! @{ +/** + * @brief This structure represents a text string to draw. + * + * Parameters match cv::putText(). + */ +struct GAPI_EXPORTS_W_SIMPLE Text +{ + /** + * @brief Text constructor + * + * @param text_ The text string to be drawn + * @param org_ The bottom-left corner of the text string in the image + * @param ff_ The font type, see #HersheyFonts + * @param fs_ The font scale factor that is multiplied by the font-specific base size + * @param color_ The text color + * @param thick_ The thickness of the lines used to draw a text + * @param lt_ The line type. See #LineTypes + * @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner + */ + GAPI_WRAP + Text(const std::string& text_, + const cv::Point& org_, + int ff_, + double fs_, + const cv::Scalar& color_, + int thick_ = 1, + int lt_ = 8, + bool bottom_left_origin_ = false) : + text(text_), org(org_), ff(ff_), fs(fs_), + color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_) + { + } + + GAPI_WRAP + Text() = default; + + /*@{*/ + GAPI_PROP_RW std::string text; //!< The text string to be drawn + GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the text string in the image + GAPI_PROP_RW int ff; //!< The font type, see #HersheyFonts + GAPI_PROP_RW double fs; //!< The font scale factor that is multiplied by the font-specific base size + GAPI_PROP_RW cv::Scalar color; //!< The text color + GAPI_PROP_RW int thick; //!< The thickness of the lines used to draw a text + GAPI_PROP_RW int lt; //!< The line type. See #LineTypes + GAPI_PROP_RW bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner + /*@{*/ +}; + +/** + * @brief This structure represents a text string to draw using + * FreeType renderer. + * + * If OpenCV is built without FreeType support, this primitive will + * fail at the execution stage. + */ +struct FText +{ + /** + * @brief FText constructor + * + * @param text_ The text string to be drawn + * @param org_ The bottom-left corner of the text string in the image + * @param fh_ The height of text + * @param color_ The text color + */ + FText(const std::wstring& text_, + const cv::Point& org_, + int fh_, + const cv::Scalar& color_) : + text(text_), org(org_), fh(fh_), color(color_) + { + } + + FText() = default; + + /*@{*/ + std::wstring text; //!< The text string to be drawn + cv::Point org; //!< The bottom-left corner of the text string in the image + int fh; //!< The height of text + cv::Scalar color; //!< The text color + /*@{*/ +}; + +/** + * @brief This structure represents a rectangle to draw. + * + * Parameters match cv::rectangle(). + */ +struct GAPI_EXPORTS_W_SIMPLE Rect +{ + /** + * @brief Rect constructor + * + * @param rect_ Coordinates of the rectangle + * @param color_ The bottom-left corner of the text string in the image + * @param thick_ The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle + * @param lt_ The type of the line. See #LineTypes + * @param shift_ The number of fractional bits in the point coordinates + */ + Rect(const cv::Rect& rect_, + const cv::Scalar& color_, + int thick_ = 1, + int lt_ = 8, + int shift_ = 0) : + rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_) + { + } + + GAPI_WRAP + Rect() = default; + + /*@{*/ + GAPI_PROP_RW cv::Rect rect; //!< Coordinates of the rectangle + GAPI_PROP_RW cv::Scalar color; //!< The rectangle color or brightness (grayscale image) + GAPI_PROP_RW int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle + GAPI_PROP_RW int lt; //!< The type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates + /*@{*/ +}; + +/** + * @brief This structure represents a circle to draw. + * + * Parameters match cv::circle(). + */ +struct GAPI_EXPORTS_W_SIMPLE Circle +{ + /** + * @brief Circle constructor + * + * @param center_ The center of the circle + * @param radius_ The radius of the circle + * @param color_ The color of the circle + * @param thick_ The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn + * @param lt_ The Type of the circle boundary. See #LineTypes + * @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value + */ + GAPI_WRAP + Circle(const cv::Point& center_, + int radius_, + const cv::Scalar& color_, + int thick_ = 1, + int lt_ = 8, + int shift_ = 0) : + center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_) + { + } + + GAPI_WRAP + Circle() = default; + + /*@{*/ + GAPI_PROP_RW cv::Point center; //!< The center of the circle + GAPI_PROP_RW int radius; //!< The radius of the circle + GAPI_PROP_RW cv::Scalar color; //!< The color of the circle + GAPI_PROP_RW int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn + GAPI_PROP_RW int lt; //!< The Type of the circle boundary. See #LineTypes + GAPI_PROP_RW int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value + /*@{*/ +}; + +/** + * @brief This structure represents a line to draw. + * + * Parameters match cv::line(). + */ +struct GAPI_EXPORTS_W_SIMPLE Line +{ + /** + * @brief Line constructor + * + * @param pt1_ The first point of the line segment + * @param pt2_ The second point of the line segment + * @param color_ The line color + * @param thick_ The thickness of line + * @param lt_ The Type of the line. See #LineTypes + * @param shift_ The number of fractional bits in the point coordinates + */ + GAPI_WRAP + Line(const cv::Point& pt1_, + const cv::Point& pt2_, + const cv::Scalar& color_, + int thick_ = 1, + int lt_ = 8, + int shift_ = 0) : + pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_) + { + } + + GAPI_WRAP + Line() = default; + + /*@{*/ + GAPI_PROP_RW cv::Point pt1; //!< The first point of the line segment + GAPI_PROP_RW cv::Point pt2; //!< The second point of the line segment + GAPI_PROP_RW cv::Scalar color; //!< The line color + GAPI_PROP_RW int thick; //!< The thickness of line + GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates + /*@{*/ +}; + +/** + * @brief This structure represents a mosaicing operation. + * + * Mosaicing is a very basic method to obfuscate regions in the image. + */ +struct GAPI_EXPORTS_W_SIMPLE Mosaic +{ + /** + * @brief Mosaic constructor + * + * @param mos_ Coordinates of the mosaic + * @param cellSz_ Cell size (same for X, Y) + * @param decim_ Decimation (0 stands for no decimation) + */ + Mosaic(const cv::Rect& mos_, + int cellSz_, + int decim_) : + mos(mos_), cellSz(cellSz_), decim(decim_) + { + } + + GAPI_WRAP + Mosaic() : cellSz(0), decim(0) {} + + /*@{*/ + GAPI_PROP_RW cv::Rect mos; //!< Coordinates of the mosaic + GAPI_PROP_RW int cellSz; //!< Cell size (same for X, Y) + GAPI_PROP_RW int decim; //!< Decimation (0 stands for no decimation) + /*@{*/ +}; + +/** + * @brief This structure represents an image to draw. + * + * Image is blended on a frame using the specified mask. + */ +struct GAPI_EXPORTS_W_SIMPLE Image +{ + /** + * @brief Mosaic constructor + * + * @param org_ The bottom-left corner of the image + * @param img_ Image to draw + * @param alpha_ Alpha channel for image to draw (same size and number of channels) + */ + GAPI_WRAP + Image(const cv::Point& org_, + const cv::Mat& img_, + const cv::Mat& alpha_) : + org(org_), img(img_), alpha(alpha_) + { + } + + GAPI_WRAP + Image() = default; + + /*@{*/ + GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the image + GAPI_PROP_RW cv::Mat img; //!< Image to draw + GAPI_PROP_RW cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels) + /*@{*/ +}; + +/** + * @brief This structure represents a polygon to draw. + */ +struct GAPI_EXPORTS_W_SIMPLE Poly +{ + /** + * @brief Mosaic constructor + * + * @param points_ Points to connect + * @param color_ The line color + * @param thick_ The thickness of line + * @param lt_ The Type of the line. See #LineTypes + * @param shift_ The number of fractional bits in the point coordinate + */ + GAPI_WRAP + Poly(const std::vector& points_, + const cv::Scalar& color_, + int thick_ = 1, + int lt_ = 8, + int shift_ = 0) : + points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_) + { + } + + GAPI_WRAP + Poly() = default; + + /*@{*/ + GAPI_PROP_RW std::vector points; //!< Points to connect + GAPI_PROP_RW cv::Scalar color; //!< The line color + GAPI_PROP_RW int thick; //!< The thickness of line + GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinate + /*@{*/ +}; + +using Prim = util::variant + < Text + , FText + , Rect + , Circle + , Line + , Mosaic + , Image + , Poly + >; + +using Prims = std::vector; +//! @} gapi_draw_prims + +} // namespace draw +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_RENDER_TYPES_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/rmat.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/rmat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..46989191b34d7c906dbb0c4435a4fd0b4afce426 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/rmat.hpp @@ -0,0 +1,160 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_RMAT_HPP +#define OPENCV_GAPI_RMAT_HPP + +#include +#include + +// Forward declaration +namespace cv { +namespace gapi { +namespace s11n { +struct IOStream; +struct IIStream; +} // namespace s11n +} // namespace gapi +} // namespace cv + +namespace cv { + +// "Remote Mat", a general class which provides an abstraction layer over the data +// storage and placement (host, remote device etc) and allows to access this data. +// +// The device specific implementation is hidden in the RMat::IAdapter class +// +// The basic flow is the following: +// * Backend which is aware of the remote device: +// - Implements own AdapterT class which is derived from RMat::IAdapter +// - Wraps device memory into RMat via make_rmat utility function: +// cv::RMat rmat = cv::make_rmat(args); +// +// * End user: +// - Writes the code which works with RMats without any knowledge of the remote device: +// void func(const cv::RMat& in_rmat, cv::RMat& out_rmat) { +// // Fetch input data from the device, get mapped memory for output +// cv::RMat::View in_view = in_rmat.access(Access::R); +// cv::RMat::View out_view = out_rmat.access(Access::W); +// performCalculations(in_view, out_view); +// // data from out_view is transferred to the device when out_view is destroyed +// } +/** \addtogroup gapi_data_structures + * @{ + */ +class GAPI_EXPORTS RMat +{ +public: + // A lightweight wrapper on image data: + // - Doesn't own the memory; + // - Doesn't implement copy semantics (it's assumed that a view is created each time + // wrapped data is being accessed); + // - Has an optional callback which is called when the view is destroyed. + class GAPI_EXPORTS View + { + public: + using DestroyCallback = std::function; + using stepsT = std::vector; + + View() = default; + View(const GMatDesc& desc, uchar* data, const stepsT& steps = {}, DestroyCallback&& cb = nullptr); + View(const GMatDesc& desc, uchar* data, size_t step, DestroyCallback&& cb = nullptr); + + View(const View&) = delete; + View& operator=(const View&) = delete; + View(View&&) = default; + View& operator=(View&& v); + ~View() { if (m_cb) m_cb(); } + + cv::Size size() const { return m_desc.size; } + const std::vector& dims() const { return m_desc.dims; } + int cols() const { return m_desc.size.width; } + int rows() const { return m_desc.size.height; } + int type() const; + int depth() const { return m_desc.depth; } + int chan() const { return m_desc.chan; } + size_t elemSize() const { return CV_ELEM_SIZE(type()); } + + template T* ptr(int y = 0) { + return reinterpret_cast(m_data + step()*y); + } + template const T* ptr(int y = 0) const { + return reinterpret_cast(m_data + step()*y); + } + template T* ptr(int y, int x) { + return reinterpret_cast(m_data + step()*y + step(1)*x); + } + template const T* ptr(int y, int x) const { + return reinterpret_cast(m_data + step()*y + step(1)*x); + } + size_t step(size_t i = 0) const { GAPI_DbgAssert(i; + + RMat() = default; + RMat(AdapterP&& a) : m_adapter(std::move(a)) {} + GMatDesc desc() const { return m_adapter->desc(); } + + // Note: When accessed for write there is no guarantee that returned view + // will contain actual snapshot of the mapped device memory + // (no guarantee that fetch from a device is performed). The only + // guaranty is that when the view is destroyed, its data will be + // transferred to the device + View access(Access a) const { return m_adapter->access(a); } + + // Cast underlying RMat adapter to the particular adapter type, + // return nullptr if underlying type is different + template T* get() const + { + static_assert(std::is_base_of::value, "T is not derived from IAdapter!"); + GAPI_Assert(m_adapter != nullptr); + return dynamic_cast(m_adapter.get()); + } + + void serialize(cv::gapi::s11n::IOStream& os) const { + m_adapter->serialize(os); + } + +private: + AdapterP m_adapter = nullptr; +}; + +template +RMat make_rmat(Ts&&... args) { return { std::make_shared(std::forward(args)...) }; } +/** @} */ + +} //namespace cv + +#endif /* OPENCV_GAPI_RMAT_HPP */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a94f55c249af678a58f53ca99eaa502e69bd0774 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n.hpp @@ -0,0 +1,513 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020-2021 Intel Corporation + +#ifndef OPENCV_GAPI_S11N_HPP +#define OPENCV_GAPI_S11N_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +// FIXME: caused by deserialize_runarg +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) +#endif + +namespace cv { +namespace gapi { + +/** +* \addtogroup gapi_serialization +* @{ +*/ + +namespace detail { + GAPI_EXPORTS cv::GComputation getGraph(const std::vector &bytes); + + GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector &bytes); + + GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector &bytes); + + GAPI_EXPORTS std::vector getVectorOfStrings(const std::vector &bytes); + + template + cv::GCompileArgs getCompileArgs(const std::vector &bytes); + + template + cv::GRunArgs getRunArgsWithAdapters(const std::vector &bytes); +} // namespace detail + +/** @brief Serialize a graph represented by GComputation into an array of bytes. + * + * Check different overloads for more examples. + * @param c GComputation to serialize. + * @return serialized vector of bytes. + */ +GAPI_EXPORTS std::vector serialize(const cv::GComputation &c); + +/** @overload + * @param ca GCompileArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GCompileArgs& ca); + +/** @overload + * @param ma GMetaArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GMetaArgs& ma); + +/** @overload + * @param ra GRunArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GRunArgs& ra); + +/** @overload + * @param vs std::vector to serialize. + */ +GAPI_EXPORTS std::vector serialize(const std::vector& vs); + +/** + * @private + */ +template static inline +T deserialize(const std::vector &bytes); + +/** @brief Deserialize GComputation from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GComputation object. + */ +template<> inline +cv::GComputation deserialize(const std::vector &bytes) { + return detail::getGraph(bytes); +} + +/** @brief Deserialize GMetaArgs from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GMetaArgs object. + */ +template<> inline +cv::GMetaArgs deserialize(const std::vector &bytes) { + return detail::getMetaArgs(bytes); +} + +/** @brief Deserialize GRunArgs from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GRunArgs object. + */ +template<> inline +cv::GRunArgs deserialize(const std::vector &bytes) { + return detail::getRunArgs(bytes); +} + +/** @brief Deserialize std::vector from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized std::vector object. + */ +template<> inline +std::vector deserialize(const std::vector &bytes) { + return detail::getVectorOfStrings(bytes); +} + +/** + * @brief Deserialize GCompileArgs which types were specified in the template from a byte array. + * + * @note cv::gapi::s11n::detail::S11N template specialization must be provided to make a custom type + * in GCompileArgs deserializable. + * + * @param bytes vector of bytes to deserialize GCompileArgs object from. + * @return GCompileArgs object. + * @see GCompileArgs cv::gapi::s11n::detail::S11N + */ +template inline +typename std::enable_if::value, GCompileArgs>:: +type deserialize(const std::vector &bytes) { + return detail::getCompileArgs(bytes); +} + +/** + * @brief Deserialize GRunArgs including RMat and MediaFrame objects if any from a byte array. + * + * Adapter types are specified in the template. + * @note To be used properly specified adapter types must overload their deserialize() method. + * @param bytes vector of bytes to deserialize GRunArgs object from. + * @return GRunArgs including RMat and MediaFrame objects if any. + * @see RMat MediaFrame + */ +template inline +typename std::enable_if::value, GRunArgs>:: +type deserialize(const std::vector &bytes) { + return detail::getRunArgsWithAdapters(bytes); +} +} // namespace gapi +} // namespace cv + +namespace cv { +namespace gapi { +namespace s11n { + +/** @brief This structure is an interface for serialization routines. + * + * It's main purpose is to provide multiple overloads for operator<<() + * with basic C++ in addition to OpenCV/G-API types. + * + * This sctructure can be inherited and further extended with additional types. + * + * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter + * in serialize() method. + */ +struct GAPI_EXPORTS IOStream { + virtual ~IOStream() = default; + // Define the native support for basic C++ types at the API level: + virtual IOStream& operator<< (bool) = 0; + virtual IOStream& operator<< (char) = 0; + virtual IOStream& operator<< (unsigned char) = 0; + virtual IOStream& operator<< (short) = 0; + virtual IOStream& operator<< (unsigned short) = 0; + virtual IOStream& operator<< (int) = 0; + virtual IOStream& operator<< (uint32_t) = 0; + virtual IOStream& operator<< (uint64_t) = 0; + virtual IOStream& operator<< (float) = 0; + virtual IOStream& operator<< (double) = 0; + virtual IOStream& operator<< (const std::string&) = 0; +}; + +/** @brief This structure is an interface for deserialization routines. + * + * It's main purpose is to provide multiple overloads for operator>>() + * with basic C++ in addition to OpenCV/G-API types. + * + * This structure can be inherited and further extended with additional types. + * + * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter + * in deserialize() method. + */ +struct GAPI_EXPORTS IIStream { + virtual ~IIStream() = default; + virtual IIStream& operator>> (bool &) = 0; + virtual IIStream& operator>> (std::vector::reference) = 0; + virtual IIStream& operator>> (char &) = 0; + virtual IIStream& operator>> (unsigned char &) = 0; + virtual IIStream& operator>> (short &) = 0; + virtual IIStream& operator>> (unsigned short &) = 0; + virtual IIStream& operator>> (int &) = 0; + virtual IIStream& operator>> (float &) = 0; + virtual IIStream& operator>> (double &) = 0; + virtual IIStream& operator >> (uint32_t &) = 0; + virtual IIStream& operator >> (uint64_t &) = 0; + virtual IIStream& operator>> (std::string &) = 0; +}; + +namespace detail { +GAPI_EXPORTS std::unique_ptr getInStream(const std::vector &bytes); +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// S11N operators +// Note: operators for basic types are defined in IIStream/IOStream + +// OpenCV types //////////////////////////////////////////////////////////////// + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point &pt); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Point &pt); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point2f &pt); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Point2f &pt); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Point3f &pt); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Point3f &pt); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Size &sz); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Size &sz); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Rect &rc); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Rect &rc); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Scalar &s); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Scalar &s); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Mat &m); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Mat &m); + +// FIXME: for GRunArgs serialization +#if !defined(GAPI_STANDALONE) +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat & um); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat & um); +#endif // !defined(GAPI_STANDALONE) + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::RMat &r); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &issptr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &issptr); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &vr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &vr); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &opr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &opr); + +/// @private -- Exclude this function from OpenCV documentation +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &mf); +/// @private -- Exclude this function from OpenCV documentation +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &mf); + +// Generic STL types //////////////////////////////////////////////////////////////// +template +IOStream& operator<< (IOStream& os, const std::map &m) { + const uint32_t sz = static_cast(m.size()); + os << sz; + for (const auto& it : m) os << it.first << it.second; + return os; +} +template +IIStream& operator>> (IIStream& is, std::map &m) { + m.clear(); + uint32_t sz = 0u; + is >> sz; + for (std::size_t i = 0; i < sz; ++i) { + K k{}; + V v{}; + is >> k >> v; + m[k] = v; + } + return is; +} + +template +IOStream& operator<< (IOStream& os, const std::unordered_map &m) { + const uint32_t sz = static_cast(m.size()); + os << sz; + for (auto &&it : m) os << it.first << it.second; + return os; +} +template +IIStream& operator>> (IIStream& is, std::unordered_map &m) { + m.clear(); + uint32_t sz = 0u; + is >> sz; + for (std::size_t i = 0; i < sz; ++i) { + K k{}; + V v{}; + is >> k >> v; + m[k] = v; + } + return is; +} + +template +IOStream& operator<< (IOStream& os, const std::vector &ts) { + const uint32_t sz = static_cast(ts.size()); + os << sz; + for (auto &&v : ts) os << v; + return os; +} +template +IIStream& operator>> (IIStream& is, std::vector &ts) { + uint32_t sz = 0u; + is >> sz; + if (sz == 0u) { + ts.clear(); + } + else { + ts.resize(sz); + for (std::size_t i = 0; i < sz; ++i) is >> ts[i]; + } + return is; +} + +// Generic: variant serialization +namespace detail { +template +IOStream& put_v(IOStream&, const V&, std::size_t) { + GAPI_Error("variant>>: requested index is invalid"); +} + +template +IOStream& put_v(IOStream& os, const V& v, std::size_t x) { + return (x == 0u) + ? os << cv::util::get(v) + : put_v(os, v, x-1); +} + +template +IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) { + GAPI_Error("variant<<: requested index is invalid"); +} + +template +IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) { + if (i == gi) { + X x{}; + is >> x; + v = V{std::move(x)}; + return is; + } else return get_v(is, v, i+1, gi); +} +} // namespace detail + +//! @overload +template +IOStream& operator<< (IOStream& os, const cv::util::variant &v) { + os << static_cast(v.index()); + return detail::put_v, Ts...>(os, v, v.index()); +} +//! @overload +template +IIStream& operator>> (IIStream& is, cv::util::variant &v) { + int idx = -1; + is >> idx; + GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts)); + return detail::get_v, Ts...>(is, v, 0u, idx); +} + +// FIXME: consider a better solution +/// @private -- Exclude this function from OpenCV documentation +template +void getRunArgByIdx (IIStream& is, cv::util::variant &v, uint32_t idx) { + is = detail::get_v, Ts...>(is, v, 0u, idx); +} +} // namespace s11n + +namespace detail +{ +template struct try_deserialize_comparg; + +template<> struct try_deserialize_comparg> { +static cv::util::optional exec(const std::string&, cv::gapi::s11n::IIStream&) { + return { }; + } +}; + +template +struct try_deserialize_comparg> { +static cv::util::optional exec(const std::string& tag, cv::gapi::s11n::IIStream& is) { + if (tag == cv::detail::CompileArgTag::tag()) { + static_assert(cv::gapi::s11n::detail::has_S11N_spec::value, + "cv::gapi::deserialize expects Types to have S11N " + "specializations with deserialization callbacks!"); + return cv::util::optional( + GCompileArg { cv::gapi::s11n::detail::S11N::deserialize(is) }); + } + return try_deserialize_comparg>::exec(tag, is); +} +}; + +template +struct deserialize_arg_with_adapter; + +template +struct deserialize_arg_with_adapter { +static GRunArg exec(cv::gapi::s11n::IIStream& is) { + std::unique_ptr ptr(new TA); + ptr->deserialize(is); + return GRunArg { RA(std::move(ptr)) }; +} +}; + +template +struct deserialize_arg_with_adapter { +static GRunArg exec(cv::gapi::s11n::IIStream&) { + GAPI_Error("No suitable adapter class found during RMat/MediaFrame deserialization. " + "Please, make sure you've passed them in cv::gapi::deserialize() template"); + return GRunArg{}; +} +}; + +template +struct deserialize_runarg { +static GRunArg exec(cv::gapi::s11n::IIStream& is, uint32_t idx) { + if (idx == GRunArg::index_of()) { + // Type or void (if not found) + using TA = typename cv::util::find_adapter_impl::type; + return deserialize_arg_with_adapter::exec(is); + } else if (idx == GRunArg::index_of()) { + // Type or void (if not found) + using TA = typename cv::util::find_adapter_impl::type; + return deserialize_arg_with_adapter::exec(is); + } else { // not an adapter holding type runarg - use default deserialization + GRunArg arg; + getRunArgByIdx(is, arg, idx); + return arg; + } +} +}; + +template +inline cv::util::optional tryDeserializeCompArg(const std::string& tag, + const std::vector& sArg) { + std::unique_ptr pArgIs = cv::gapi::s11n::detail::getInStream(sArg); + return try_deserialize_comparg>::exec(tag, *pArgIs); +} + +template +cv::GCompileArgs getCompileArgs(const std::vector &sArgs) { + cv::GCompileArgs args; + + std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(sArgs); + cv::gapi::s11n::IIStream& is = *pIs; + + uint32_t sz = 0; + is >> sz; + for (uint32_t i = 0; i < sz; ++i) { + std::string tag; + is >> tag; + + std::vector sArg; + is >> sArg; + + cv::util::optional dArg = + cv::gapi::detail::tryDeserializeCompArg(tag, sArg); + + if (dArg.has_value()) + { + args.push_back(dArg.value()); + } + } + + return args; +} + +template +cv::GRunArgs getRunArgsWithAdapters(const std::vector &bytes) { + std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(bytes); + cv::gapi::s11n::IIStream& is = *pIs; + cv::GRunArgs args; + + uint32_t sz = 0; + is >> sz; + for (uint32_t i = 0; i < sz; ++i) { + uint32_t idx = 0; + is >> idx; + args.push_back(cv::gapi::detail::deserialize_runarg::exec(is, idx)); + } + + return args; +} +} // namespace detail +/** @} */ + +} // namespace gapi +} // namespace cv + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // OPENCV_GAPI_S11N_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n/base.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n/base.hpp new file mode 100644 index 0000000000000000000000000000000000000000..760e8515f6ac2c8449b9b2b16780b943375e2b0c --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/s11n/base.hpp @@ -0,0 +1,80 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020-2021 Intel Corporation + +#ifndef OPENCV_GAPI_S11N_BASE_HPP +#define OPENCV_GAPI_S11N_BASE_HPP + +#include +#include + +namespace cv { +namespace gapi { + +/** + * @brief This namespace contains G-API serialization and + * deserialization functions and data structures. + */ +namespace s11n { +struct IOStream; +struct IIStream; + +namespace detail { + +//! @addtogroup gapi_serialization +//! @{ + +struct NotImplemented { +}; + +/** @brief This structure allows to implement serialization routines for custom types. + * + * The default S11N for custom types is not implemented. + * + * @note When providing an overloaded implementation for S11N with your type + * don't inherit it from NotImplemented structure. + * + * @note There are lots of overloaded >> and << operators for basic and OpenCV/G-API types + * which can be utilized when serializing a custom type. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp S11N usage + * + */ +template +struct S11N: public NotImplemented { + /** + * @brief This function allows user to serialize their custom type. + * + * @note The default overload throws an exception if called. User need to + * properly overload the function to use it. + */ + static void serialize(IOStream &, const T &) { + GAPI_Error("No serialization routine is provided!"); + } + /** + * @brief This function allows user to deserialize their custom type. + * + * @note The default overload throws an exception if called. User need to + * properly overload the function to use it. + */ + static T deserialize(IIStream &) { + GAPI_Error("No deserialization routine is provided!"); + } +}; + +/// @private -- Exclude this struct from OpenCV documentation +template struct has_S11N_spec { + static constexpr bool value = !std::is_base_of::type>>::value; +}; +//! @} gapi_serialization + +} // namespace detail +} // namespace s11n +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_S11N_BASE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/stereo.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/stereo.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9b00267082caaf97c19bdb7b055baa537972ae5f --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/stereo.hpp @@ -0,0 +1,85 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distereoibution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STEREO_HPP +#define OPENCV_GAPI_STEREO_HPP + +#include +#include +#include + +namespace cv { +namespace gapi { + +/** + * The enum specified format of result that you get from @ref cv::gapi::stereo. + */ +enum class StereoOutputFormat { + DEPTH_FLOAT16, ///< Floating point 16 bit value, CV_16FC1. + ///< This identifier is deprecated, use DEPTH_16F instead. + DEPTH_FLOAT32, ///< Floating point 32 bit value, CV_32FC1 + ///< This identifier is deprecated, use DEPTH_16F instead. + DISPARITY_FIXED16_11_5, ///< 16 bit signed: first bit for sign, + ///< 10 bits for integer part, + ///< 5 bits for fractional part. + ///< This identifier is deprecated, + ///< use DISPARITY_16Q_10_5 instead. + DISPARITY_FIXED16_12_4, ///< 16 bit signed: first bit for sign, + ///< 11 bits for integer part, + ///< 4 bits for fractional part. + ///< This identifier is deprecated, + ///< use DISPARITY_16Q_11_4 instead. + DEPTH_16F = DEPTH_FLOAT16, ///< Same as DEPTH_FLOAT16 + DEPTH_32F = DEPTH_FLOAT32, ///< Same as DEPTH_FLOAT32 + DISPARITY_16Q_10_5 = DISPARITY_FIXED16_11_5, ///< Same as DISPARITY_FIXED16_11_5 + DISPARITY_16Q_11_4 = DISPARITY_FIXED16_12_4 ///< Same as DISPARITY_FIXED16_12_4 +}; + + +/** + * @brief This namespace contains G-API Operation Types for Stereo and + * related functionality. + */ +namespace calib3d { + +G_TYPED_KERNEL(GStereo, , "org.opencv.stereo") { + static GMatDesc outMeta(const GMatDesc &left, const GMatDesc &right, const StereoOutputFormat of) { + GAPI_Assert(left.chan == 1); + GAPI_Assert(left.depth == CV_8U); + + GAPI_Assert(right.chan == 1); + GAPI_Assert(right.depth == CV_8U); + + switch(of) { + case StereoOutputFormat::DEPTH_FLOAT16: + return left.withDepth(CV_16FC1); + case StereoOutputFormat::DEPTH_FLOAT32: + return left.withDepth(CV_32FC1); + case StereoOutputFormat::DISPARITY_FIXED16_11_5: + case StereoOutputFormat::DISPARITY_FIXED16_12_4: + return left.withDepth(CV_16SC1); + default: + GAPI_Error("Unknown output format!"); + } + } +}; + +} // namespace calib3d + +/** @brief Computes disparity/depth map for the specified stereo-pair. +The function computes disparity or depth map depending on passed StereoOutputFormat argument. + +@param left 8-bit single-channel left image of @ref CV_8UC1 type. +@param right 8-bit single-channel right image of @ref CV_8UC1 type. +@param of enum to specified output kind: depth or disparity and corresponding type +*/ +GAPI_EXPORTS GMat stereo(const GMat& left, + const GMat& right, + const StereoOutputFormat of = StereoOutputFormat::DEPTH_FLOAT32); +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STEREO_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/cap.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/cap.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9c2185c1ab46fc393494e07d3146c185d27ac18b --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/cap.hpp @@ -0,0 +1,149 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_CAP_HPP +#define OPENCV_GAPI_STREAMING_CAP_HPP + +/** + * YOUR ATTENTION PLEASE! + * + * This is a header-only implementation of cv::VideoCapture-based + * Stream source. It is not built by default with G-API as G-API + * doesn't depend on videoio module. + * + * If you want to use it in your application, please make sure + * videioio is available in your OpenCV package and is linked to your + * application. + * + * Note for developers: please don't put videoio dependency in G-API + * because of this file. + */ +#include +#include + +#include +#include +#include + +namespace cv { +namespace gapi { +namespace wip { + +/** + * @brief OpenCV's VideoCapture-based streaming source. + * + * This class implements IStreamSource interface. + * Its constructor takes the same parameters as cv::VideoCapture does. + * + * Please make sure that videoio OpenCV module is available before using + * this in your application (G-API doesn't depend on it directly). + * + * @note stream sources are passed to G-API via shared pointers, so + * please gapi::make_src<> to create objects and ptr() to pass a + * GCaptureSource to cv::gin(). + */ +class GCaptureSource: public IStreamSource +{ +public: + explicit GCaptureSource(int id, const std::map &properties = {}) + : cap(id) { prep(properties); } + + explicit GCaptureSource(const std::string &path, + const std::map &properties = {}) + : cap(path) { prep(properties); } + + void set(int propid, double value) { + cap.set(propid, value); + } + + // TODO: Add more constructor overloads to make it + // fully compatible with VideoCapture's interface. + +protected: + cv::VideoCapture cap; + cv::Mat first; + bool first_pulled = false; + int64_t counter = 0; + + void prep(const std::map &properties) + { + for (const auto &it : properties) { + cap.set(it.first, it.second); + } + + // Prepare first frame to report its meta to engine + // when needed + GAPI_Assert(first.empty()); + cv::Mat tmp; + if (!cap.read(tmp)) + { + GAPI_Error("Couldn't grab the very first frame"); + } + // NOTE: Some decode/media VideoCapture backends continue + // owning the video buffer under cv::Mat so in order to + // process it safely in a highly concurrent pipeline, clone() + // is the only right way. + first = tmp.clone(); + } + + virtual bool pull(cv::gapi::wip::Data &data) override + { + if (!first_pulled) + { + GAPI_Assert(!first.empty()); + first_pulled = true; + data = first; // no need to clone here since it was cloned already + } + else + { + if (!cap.isOpened()) return false; + + cv::Mat frame; + if (!cap.read(frame)) + { + // end-of-stream happened + return false; + } + // Same reason to clone as in prep() + data = frame.clone(); + } + // Tag data with seq_id/ts + const auto now = std::chrono::system_clock::now(); + const auto dur = std::chrono::duration_cast + (now.time_since_epoch()); + data.meta[cv::gapi::streaming::meta_tag::timestamp] = int64_t{dur.count()}; + data.meta[cv::gapi::streaming::meta_tag::seq_id] = int64_t{counter++}; + return true; + } + + virtual GMetaArg descr_of() const override + { + GAPI_Assert(!first.empty()); + return cv::GMetaArg{cv::descr_of(first)}; + } +}; + +// NB: Overload for using from python +GAPI_EXPORTS_W cv::Ptr +inline make_capture_src(const std::string& path, + const std::map& properties = {}) +{ + return make_src(path, properties); +} + +// NB: Overload for using from python +GAPI_EXPORTS_W cv::Ptr +inline make_capture_src(const int id, + const std::map& properties = {}) +{ + return make_src(id, properties); +} + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_CAP_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/desync.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/desync.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0e04f5beb93bcf4773c7909646c1ecc31df84f2f --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/desync.hpp @@ -0,0 +1,86 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020-2021 Intel Corporation + + +#ifndef OPENCV_GAPI_GSTREAMING_DESYNC_HPP +#define OPENCV_GAPI_GSTREAMING_DESYNC_HPP + +#include + +#include +#include +#include +#include +#include + +namespace cv { +namespace gapi { +namespace streaming { + +namespace detail { +struct GDesync { + static const char *id() { + return "org.opencv.streaming.desync"; + } + + // An universal yield for desync. + // Yields output objects according to the input Types... + // Reuses gkernel machinery. + // FIXME: This function can be generic and declared in gkernel.hpp + // (it is there already, but a part of GKernelType[M] + template + static std::tuple yield(cv::GCall &call, cv::detail::Seq) { + return std::make_tuple(cv::detail::Yield::yield(call, IIs)...); + } +}; + +template +G desync(const G &g) { + cv::GKernel k{ + GDesync::id() // kernel id + , "" // kernel tag + , [](const GMetaArgs &a, const GArgs &) {return a;} // outMeta callback + , {cv::detail::GTypeTraits::shape} // output Shape + , {cv::detail::GTypeTraits::op_kind} // input data kinds + , {cv::detail::GObtainCtor::get()} // output template ctors + , {cv::detail::GTypeTraits::op_kind} // output data kinds + }; + cv::GCall call(std::move(k)); + call.pass(g); + return std::get<0>(GDesync::yield(call, cv::detail::MkSeq<1>::type())); +} +} // namespace detail + +/** + * @brief Starts a desynchronized branch in the graph. + * + * This operation takes a single G-API data object and returns a + * graph-level "duplicate" of this object. + * + * Operations which use this data object can be desynchronized + * from the rest of the graph. + * + * This operation has no effect when a GComputation is compiled with + * regular cv::GComputation::compile(), since cv::GCompiled objects + * always produce their full output vectors. + * + * This operation only makes sense when a GComputation is compiled in + * streaming mode with cv::GComputation::compileStreaming(). If this + * operation is used and there are desynchronized outputs, the user + * should use a special version of cv::GStreamingCompiled::pull() + * which produces an array of cv::util::optional<> objects. + * + * @note This feature is highly experimental now and is currently + * limited to a single GMat/GFrame argument only. + */ +GAPI_EXPORTS GMat desync(const GMat &g); +GAPI_EXPORTS GFrame desync(const GFrame &f); + +} // namespace streaming +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_GSTREAMING_DESYNC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/format.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/format.hpp new file mode 100644 index 0000000000000000000000000000000000000000..739a3852a64d09e15c886ea06bc71e05062d0557 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/format.hpp @@ -0,0 +1,94 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_GSTREAMING_FORMAT_HPP +#define OPENCV_GAPI_GSTREAMING_FORMAT_HPP + +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace streaming { + +GAPI_EXPORTS cv::GKernelPackage kernels(); + +G_API_OP(GBGR, , "org.opencv.streaming.BGR") +{ + static GMatDesc outMeta(const GFrameDesc& in) { return GMatDesc{CV_8U, 3, in.size}; } +}; + +G_API_OP(GY, , "org.opencv.streaming.Y") { + static GMatDesc outMeta(const GFrameDesc& frameDesc) { + return GMatDesc { CV_8U, 1, frameDesc.size , false }; + } +}; + +G_API_OP(GUV, , "org.opencv.streaming.UV") { + static GMatDesc outMeta(const GFrameDesc& frameDesc) { + return GMatDesc { CV_8U, 2, cv::Size(frameDesc.size.width / 2, frameDesc.size.height / 2), + false }; + } +}; + +/** @brief Gets bgr plane from input frame + +@note Function textual ID is "org.opencv.streaming.BGR" + +@param in Input frame +@return Image in BGR format +*/ +GAPI_EXPORTS cv::GMat BGR(const cv::GFrame& in); + +/** @brief Extracts Y plane from media frame. + +Output image is 8-bit 1-channel image of @ref CV_8UC1. + +@note Function textual ID is "org.opencv.streaming.Y" + +@param frame input media frame. +*/ +GAPI_EXPORTS GMat Y(const cv::GFrame& frame); + +/** @brief Extracts UV plane from media frame. + +Output image is 8-bit 2-channel image of @ref CV_8UC2. + +@note Function textual ID is "org.opencv.streaming.UV" + +@param frame input media frame. +*/ +GAPI_EXPORTS GMat UV(const cv::GFrame& frame); +} // namespace streaming + +//! @addtogroup gapi_transform +//! @{ +/** @brief Makes a copy of the input image. Note that this copy may be not real +(no actual data copied). Use this function to maintain graph contracts, +e.g when graph's input needs to be passed directly to output, like in Streaming mode. + +@note Function textual ID is "org.opencv.streaming.copy" + +@param in Input image +@return Copy of the input +*/ +GAPI_EXPORTS_W GMat copy(const GMat& in); + +/** @brief Makes a copy of the input frame. Note that this copy may be not real +(no actual data copied). Use this function to maintain graph contracts, +e.g when graph's input needs to be passed directly to output, like in Streaming mode. + +@note Function textual ID is "org.opencv.streaming.copy" + +@param in Input frame +@return Copy of the input +*/ +GAPI_EXPORTS GFrame copy(const GFrame& in); +//! @} gapi_transform + +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_GSTREAMING_FORMAT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c566656cb61a06b5bbbd018c83fd9359a1dc6cad --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp @@ -0,0 +1,59 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP +#define OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP + +#include +#include + +#include +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace gst { + +class GAPI_EXPORTS_W GStreamerPipeline +{ +public: + class Priv; + + GAPI_WRAP explicit GStreamerPipeline(const std::string& pipeline); + IStreamSource::Ptr getStreamingSource(const std::string& appsinkName, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + virtual ~GStreamerPipeline(); + +protected: + explicit GStreamerPipeline(std::unique_ptr priv); + + std::unique_ptr m_priv; +}; + +} // namespace gst + +using GStreamerPipeline = gst::GStreamerPipeline; + +// NB: Function for using from python +// FIXME: a separate function is created due to absence of wrappers for `shared_ptr<> ` +// Ideally would be to wrap the `GStreamerPipeline::getStreamingSource()` method as is +GAPI_EXPORTS_W cv::Ptr +inline get_streaming_source(cv::Ptr& pipeline, + const std::string& appsinkName, + const GStreamerSource::OutputType outputType + = GStreamerSource::OutputType::MAT) +{ + return pipeline->getStreamingSource(appsinkName, outputType); +} + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b8a5ae3121f4d42ddf9413ab7ed47169c81ae7b --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp @@ -0,0 +1,97 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP +#define OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP + +#include +#include + +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace gst { + +/** + * @brief OpenCV's GStreamer streaming source. + * Streams cv::Mat-s/cv::MediaFrame from passed GStreamer pipeline. + * + * This class implements IStreamSource interface. + * + * To create GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType' + * arguments into constructor. + * 'pipeline' should represent GStreamer pipeline in form of textual description. + * Almost any custom pipeline is supported which can be successfully ran via gst-launch. + * The only two limitations are: + * - there should be __one__ appsink element in the pipeline to pass data to OpenCV app. + * Pipeline can actually contain many sink elements, but it must have one and only one + * appsink among them. + * + * - data passed to appsink should be video-frame in NV12 or GRAY8 format. + * + * 'outputType' is used to select type of output data to produce: 'cv::MediaFrame' or 'cv::Mat'. + * To produce 'cv::MediaFrame'-s you need to pass 'GStreamerSource::OutputType::FRAME' and, + * correspondingly, 'GStreamerSource::OutputType::MAT' to produce 'cv::Mat'-s. + * Please note, that in the last case, output 'cv::Mat' will be of BGR format, internal conversion + * from NV12 / GRAY8 GStreamer data will happen. + * Default value for 'outputType' is 'GStreamerSource::OutputType::MAT'. + * + * @note Stream sources are passed to G-API via shared pointers, so please use gapi::make_src<> + * to create objects and ptr() to pass a GStreamerSource to cv::gin(). + * + * @note You need to build OpenCV with GStreamer support to use this class. + */ + +class GStreamerPipelineFacade; + +class GAPI_EXPORTS GStreamerSource : public IStreamSource +{ +public: + class Priv; + + // Indicates what type of data should be produced by GStreamerSource: cv::MediaFrame or cv::Mat + enum class OutputType { + FRAME, + MAT + }; + + GStreamerSource(const std::string& pipeline, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + GStreamerSource(std::shared_ptr pipeline, + const std::string& appsinkName, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + + bool pull(cv::gapi::wip::Data& data) override; + GMetaArg descr_of() const override; + ~GStreamerSource() override; + +protected: + explicit GStreamerSource(std::unique_ptr priv); + + std::unique_ptr m_priv; +}; + +} // namespace gst + +using GStreamerSource = gst::GStreamerSource; + +// NB: Overload for using from python +GAPI_EXPORTS_W cv::Ptr +inline make_gst_src(const std::string& pipeline, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT) +{ + return make_src(pipeline, outputType); +} +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/meta.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/meta.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cdd3d371cb4558423bb9bd81c6f8bda193d4bc31 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/meta.hpp @@ -0,0 +1,80 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + + +#ifndef OPENCV_GAPI_GSTREAMING_META_HPP +#define OPENCV_GAPI_GSTREAMING_META_HPP + +#include +#include +#include +#include + +namespace cv { +namespace gapi { +namespace streaming { + +// FIXME: the name is debatable +namespace meta_tag { +static constexpr const char * timestamp = "org.opencv.gapi.meta.timestamp"; +static constexpr const char * seq_id = "org.opencv.gapi.meta.seq_id"; +} // namespace meta_tag + +namespace detail { +struct GMeta { + static const char *id() { + return "org.opencv.streaming.meta"; + } + // A universal yield for meta(), same as in GDesync + template + static std::tuple yield(cv::GCall &call, cv::detail::Seq) { + return std::make_tuple(cv::detail::Yield::yield(call, IIs)...); + } + // Also a universal outMeta stub here + static GMetaArgs getOutMeta(const GMetaArgs &args, const GArgs &) { + return args; + } +}; +} // namespace detail + +template +cv::GOpaque meta(G g, const std::string &tag) { + using O = cv::GOpaque; + cv::GKernel k{ + detail::GMeta::id() // kernel id + , tag // kernel tag. Use meta tag here + , &detail::GMeta::getOutMeta // outMeta callback + , {cv::detail::GTypeTraits::shape} // output Shape + , {cv::detail::GTypeTraits::op_kind} // input data kinds + , {cv::detail::GObtainCtor::get()} // output template ctors + , {cv::detail::GTypeTraits::op_kind} // output data kind + }; + cv::GCall call(std::move(k)); + call.pass(g); + return std::get<0>(detail::GMeta::yield(call, cv::detail::MkSeq<1>::type())); +} + +template +cv::GOpaque timestamp(G g) { + return meta(g, meta_tag::timestamp); +} + +template +cv::GOpaque seq_id(G g) { + return meta(g, meta_tag::seq_id); +} + +template +cv::GOpaque seqNo(G g) { + // Old name, compatibility only + return seq_id(g); +} + +} // namespace streaming +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_GSTREAMING_META_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/accel_types.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/accel_types.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b670aebd1d44c7a494d17d85d6de254fbc0cd6f5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/accel_types.hpp @@ -0,0 +1,76 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2022 Intel Corporation + +#ifndef GAPI_STREAMING_ONEVPL_ACCEL_TYPES_HPP +#define GAPI_STREAMING_ONEVPL_ACCEL_TYPES_HPP + +#include +#include + +#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +enum class AccelType: uint8_t { + HOST, + DX11, + VAAPI, + + LAST_VALUE = std::numeric_limits::max() +}; + +GAPI_EXPORTS const char* to_cstring(AccelType type); + +struct IDeviceSelector; +struct GAPI_EXPORTS Device { + friend struct IDeviceSelector; + using Ptr = void*; + + ~Device(); + const std::string& get_name() const; + Ptr get_ptr() const; + AccelType get_type() const; +private: + Device(Ptr device_ptr, const std::string& device_name, + AccelType device_type); + + std::string name; + Ptr ptr; + AccelType type; +}; + +struct GAPI_EXPORTS Context { + friend struct IDeviceSelector; + using Ptr = void*; + + ~Context(); + Ptr get_ptr() const; + AccelType get_type() const; +private: + Context(Ptr ctx_ptr, AccelType ctx_type); + Ptr ptr; + AccelType type; +}; + +GAPI_EXPORTS Device create_host_device(); +GAPI_EXPORTS Context create_host_context(); + +GAPI_EXPORTS Device create_dx11_device(Device::Ptr device_ptr, + const std::string& device_name); +GAPI_EXPORTS Context create_dx11_context(Context::Ptr ctx_ptr); + +GAPI_EXPORTS Device create_vaapi_device(Device::Ptr device_ptr, + const std::string& device_name); +GAPI_EXPORTS Context create_vaapi_context(Context::Ptr ctx_ptr); +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // GAPI_STREAMING_ONEVPL_ACCEL_TYPES_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/cfg_params.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/cfg_params.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0db9a86e58d0603b78bbb8e2d231f81093cd7ce4 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/cfg_params.hpp @@ -0,0 +1,209 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP + +#include +#include +#include + +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +/** + * @brief Public class is using for creation of onevpl::GSource instances. + * + * Class members available through methods @ref CfgParam::get_name() and @ref CfgParam::get_value() are used by + * onevpl::GSource inner logic to create or find oneVPL particular implementation + * (software/hardware, specific API version and etc.). + * + * @note Because oneVPL may provide several implementations which are satisfying with multiple (or single one) @ref CfgParam + * criteria therefore it is possible to configure `preferred` parameters. This kind of CfgParams are created + * using `is_major = false` argument in @ref CfgParam::create method and are not used by creating oneVPL particular implementations. + * Instead they fill out a "score table" to select preferable implementation from available list. Implementation are satisfying + * with most of these optional params would be chosen. + * If no one optional CfgParam params were present then first of available oneVPL implementation would be applied. + * Please get on https://spec.oneapi.io/versions/latest/elements/oneVPL/source/API_ref/VPL_disp_api_func.html?highlight=mfxcreateconfig#mfxsetconfigfilterproperty + * for using OneVPL configuration. In this schema `mfxU8 *name` represents @ref CfgParam::get_name() and + * `mfxVariant value` is @ref CfgParam::get_value() + */ +struct GAPI_EXPORTS CfgParam { + using name_t = std::string; + using value_t = cv::util::variant; + /** + * @brief frames_pool_size_name + * + * Special configuration parameter name for onevp::GSource: + * + * @note frames_pool_size_name allows to allocate surfaces pool appropriate size to keep + * decoded frames in accelerator memory ready before + * they would be consumed by onevp::GSource::pull operation. If you see + * a lot of WARNING about lack of free surface then it's time to increase + * frames_pool_size_name but be aware of accelerator free memory volume. + * If not set then MFX implementation use + * mfxFrameAllocRequest::NumFrameSuggested behavior + * + */ + static constexpr const char *frames_pool_size_name() { return "frames_pool_size"; } + static CfgParam create_frames_pool_size(size_t value); + + /** + * @brief acceleration_mode_name + * + * Special configuration parameter names for onevp::GSource: + * + * @note acceleration_mode_name allows to activate hardware acceleration & + * device memory management. + * Supported values: + * - MFX_ACCEL_MODE_VIA_D3D11 Will activate DX11 acceleration and will produces + * MediaFrames with data allocated in DX11 device memory + * + * If not set then MFX implementation will use default acceleration behavior: + * all decoding operation uses default GPU resources but MediaFrame produces + * data allocated by using host RAM + * + */ + static constexpr const char *acceleration_mode_name() { return "mfxImplDescription.AccelerationMode"; } + static CfgParam create_acceleration_mode(uint32_t value); + static CfgParam create_acceleration_mode(const char* value); + + /** + * @brief decoder_id_name + * + * Special configuration parameter names for onevp::GSource: + * + * @note decoder_id_name allows to specify VPL decoder type which MUST present + * in case of RAW video input data and MUST NOT present as CfgParam if video + * stream incapsulated into container(*.mp4, *.mkv and so on). In latter case + * onevp::GSource will determine it automatically + * Supported values: + * - MFX_CODEC_AVC + * - MFX_CODEC_HEVC + * - MFX_CODEC_MPEG2 + * - MFX_CODEC_VC1 + * - MFX_CODEC_CAPTURE + * - MFX_CODEC_VP9 + * - MFX_CODEC_AV1 + * + */ + static constexpr const char *decoder_id_name() { return "mfxImplDescription.mfxDecoderDescription.decoder.CodecID"; } + static CfgParam create_decoder_id(uint32_t value); + static CfgParam create_decoder_id(const char* value); + + static constexpr const char *implementation_name() { return "mfxImplDescription.Impl"; } + static CfgParam create_implementation(uint32_t value); + static CfgParam create_implementation(const char* value); + + + static constexpr const char *vpp_frames_pool_size_name() { return "vpp_frames_pool_size"; } + static CfgParam create_vpp_frames_pool_size(size_t value); + + static constexpr const char *vpp_in_width_name() { return "vpp.In.Width"; } + static CfgParam create_vpp_in_width(uint16_t value); + + static constexpr const char *vpp_in_height_name() { return "vpp.In.Height"; } + static CfgParam create_vpp_in_height(uint16_t value); + + static constexpr const char *vpp_in_crop_x_name() { return "vpp.In.CropX"; } + static CfgParam create_vpp_in_crop_x(uint16_t value); + + static constexpr const char *vpp_in_crop_y_name() { return "vpp.In.CropY"; } + static CfgParam create_vpp_in_crop_y(uint16_t value); + + static constexpr const char *vpp_in_crop_w_name() { return "vpp.In.CropW"; } + static CfgParam create_vpp_in_crop_w(uint16_t value); + + static constexpr const char *vpp_in_crop_h_name() { return "vpp.In.CropH"; } + static CfgParam create_vpp_in_crop_h(uint16_t value); + + + static constexpr const char *vpp_out_fourcc_name() { return "vpp.Out.FourCC"; } + static CfgParam create_vpp_out_fourcc(uint32_t value); + + static constexpr const char *vpp_out_chroma_format_name() { return "vpp.Out.ChromaFormat"; } + static CfgParam create_vpp_out_chroma_format(uint16_t value); + + static constexpr const char *vpp_out_width_name() { return "vpp.Out.Width"; } + static CfgParam create_vpp_out_width(uint16_t value); + + static constexpr const char *vpp_out_height_name() { return "vpp.Out.Height"; } + static CfgParam create_vpp_out_height(uint16_t value); + + static constexpr const char *vpp_out_crop_x_name() { return "vpp.Out.CropX"; } + static CfgParam create_vpp_out_crop_x(uint16_t value); + + static constexpr const char *vpp_out_crop_y_name() { return "vpp.Out.CropY"; } + static CfgParam create_vpp_out_crop_y(uint16_t value); + + static constexpr const char *vpp_out_crop_w_name() { return "vpp.Out.CropW"; } + static CfgParam create_vpp_out_crop_w(uint16_t value); + + static constexpr const char *vpp_out_crop_h_name() { return "vpp.Out.CropH"; } + static CfgParam create_vpp_out_crop_h(uint16_t value); + + static constexpr const char *vpp_out_pic_struct_name() { return "vpp.Out.PicStruct"; } + static CfgParam create_vpp_out_pic_struct(uint16_t value); + + static constexpr const char *vpp_out_framerate_n_name() { return "vpp.Out.FrameRateExtN"; } + static CfgParam create_vpp_out_framerate_n(uint32_t value); + + static constexpr const char *vpp_out_framerate_d_name() { return "vpp.Out.FrameRateExtD"; } + static CfgParam create_vpp_out_framerate_d(uint32_t value); + + /** + * Create generic onevp::GSource configuration parameter. + * + *@param name name of parameter. + *@param value value of parameter. + *@param is_major TRUE if parameter MUST be provided by OneVPL inner implementation, FALSE for optional (for resolve multiple available implementations). + * + */ + template + static CfgParam create(const std::string& name, ValueType&& value, bool is_major = true) { + CfgParam param(name, CfgParam::value_t(std::forward(value)), is_major); + return param; + } + + struct Priv; + + const name_t& get_name() const; + const value_t& get_value() const; + bool is_major() const; + std::string to_string() const; + + bool operator==(const CfgParam& rhs) const; + bool operator< (const CfgParam& rhs) const; + bool operator!=(const CfgParam& rhs) const; + + CfgParam& operator=(const CfgParam& src); + CfgParam& operator=(CfgParam&& src); + CfgParam(const CfgParam& src); + CfgParam(CfgParam&& src); + ~CfgParam(); +private: + CfgParam(const std::string& param_name, value_t&& param_value, bool is_major_param); + std::shared_ptr m_priv; +}; + +} //namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ec683a7527ff5392a6080bfdcef010a63d49ed5c --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp @@ -0,0 +1,105 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP +#define GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP +#include +#include +#include + +#include // GAPI_EXPORTS +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +struct GAPI_EXPORTS DataProviderException : public std::exception { + DataProviderException(const std::string& descr); + DataProviderException(std::string&& descr); + + virtual ~DataProviderException() = default; + virtual const char* what() const noexcept override; +private: + std::string reason; +}; + +struct GAPI_EXPORTS DataProviderSystemErrorException final : public DataProviderException { + DataProviderSystemErrorException(int error_code, const std::string& description = std::string()); + ~DataProviderSystemErrorException() = default; +}; + +struct GAPI_EXPORTS DataProviderUnsupportedException final : public DataProviderException { + DataProviderUnsupportedException(const std::string& description); + ~DataProviderUnsupportedException() = default; +}; + +struct GAPI_EXPORTS DataProviderImplementationException : public DataProviderException { + DataProviderImplementationException(const std::string& description); + ~DataProviderImplementationException() = default; +}; +/** + * @brief Public interface allows to customize extraction of video stream data + * used by onevpl::GSource instead of reading stream from file (by default). + * + * Interface implementation constructor MUST provide consistency and creates fully operable object. + * If error happened implementation MUST throw `DataProviderException` kind exceptions + * + * @note Interface implementation MUST manage stream and other constructed resources by itself to avoid any kind of leak. + * For simple interface implementation example please see `StreamDataProvider` in `tests/streaming/gapi_streaming_tests.cpp` + */ +struct GAPI_EXPORTS IDataProvider { + using Ptr = std::shared_ptr; + using mfx_codec_id_type = uint32_t; + + /** + * NB: here is supposed to be forward declaration of mfxBitstream + * But according to current oneVPL implementation it is impossible to forward + * declare untagged struct mfxBitstream. + * + * IDataProvider makes sense only for HAVE_VPL is ON and to keep IDataProvider + * interface API/ABI compliant between core library and user application layer + * let's introduce wrapper mfx_bitstream which inherits mfxBitstream in private + * G-API code section and declare forward for wrapper mfx_bitstream here + */ + struct mfx_bitstream; + + virtual ~IDataProvider() = default; + + /** + * The function is used by onevpl::GSource to extract codec id from data + * + */ + virtual mfx_codec_id_type get_mfx_codec_id() const = 0; + + /** + * The function is used by onevpl::GSource to extract binary data stream from @ref IDataProvider + * implementation. + * + * It MUST throw `DataProviderException` kind exceptions in fail cases. + * It MUST return MFX_ERR_MORE_DATA in EOF which considered as not-fail case. + * + * @param in_out_bitsream the input-output reference on MFX bitstream buffer which MUST be empty at the first request + * to allow implementation to allocate it by itself and to return back. Subsequent invocation of `fetch_bitstream_data` + * MUST use the previously used in_out_bitsream to avoid skipping rest of frames which haven't been consumed + * @return true for fetched data, false on EOF and throws exception on error + */ + virtual bool fetch_bitstream_data(std::shared_ptr &in_out_bitsream) = 0; + + /** + * The function is used by onevpl::GSource to check more binary data availability. + * + * It MUST return TRUE in case of EOF and NO_THROW exceptions. + * + * @return boolean value which detects end of stream + */ + virtual bool empty() const = 0; +}; +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/default.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/default.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b547e1aba9bc7acb138451cb28b663bd4f46821 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/default.hpp @@ -0,0 +1,29 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2022 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP + +#include // GAPI_EXPORTS +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +/** + * @brief Provides default device selector based on config. + */ +GAPI_EXPORTS std::shared_ptr getDefaultDeviceSelector(const std::vector& cfg_params); + +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2e2d879fba6b668bae57f4718883d33125e245ee --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp @@ -0,0 +1,61 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP +#define GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP + +#include +#include +#include +#include + +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { +struct GAPI_EXPORTS IDeviceSelector { + using Ptr = std::shared_ptr; + + struct GAPI_EXPORTS Score { + friend struct IDeviceSelector; + using Type = int16_t; + static constexpr Type MaxActivePriority = std::numeric_limits::max(); + static constexpr Type MinActivePriority = 0; + static constexpr Type MaxPassivePriority = MinActivePriority - 1; + static constexpr Type MinPassivePriority = std::numeric_limits::min(); + + Score(Type val); + ~Score(); + + operator Type () const; + Type get() const; + friend bool operator< (Score lhs, Score rhs) { + return lhs.get() < rhs.get(); + } + private: + Type value; + }; + + using DeviceScoreTable = std::map; + using DeviceContexts = std::vector; + + virtual ~IDeviceSelector(); + virtual DeviceScoreTable select_devices() const = 0; + virtual DeviceContexts select_context() = 0; +protected: + template + static Entity create(Args &&...args) { + return Entity(std::forward(args)...); + } +}; +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/source.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/source.hpp new file mode 100644 index 0000000000000000000000000000000000000000..04dc2e246d3e85d1a1038f264bb14afbdca7b2d2 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/onevpl/source.hpp @@ -0,0 +1,94 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP + +#include +#include +#include +#include +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { +using CfgParams = std::vector; + +/** + * @brief G-API streaming source based on OneVPL implementation. + * + * This class implements IStreamSource interface. + * Its constructor takes source file path (in usual way) or @ref onevpl::IDataProvider + * interface implementation (for not file-based sources). It also allows to pass-through + * oneVPL configuration parameters by using several @ref onevpl::CfgParam. + * + * @note stream sources are passed to G-API via shared pointers, so + * please gapi::make_onevpl_src<> to create objects and ptr() to pass a + * GSource to cv::gin(). + */ +class GAPI_EXPORTS GSource : public IStreamSource +{ +public: + struct Priv; + + GSource(const std::string& filePath, + const CfgParams& cfg_params = CfgParams{}); + + GSource(const std::string& filePath, + const CfgParams& cfg_params, + const std::string& device_id, + void* accel_device_ptr, + void* accel_ctx_ptr); + + GSource(const std::string& filePath, + const CfgParams& cfg_params, + const Device &device, const Context &ctx); + + GSource(const std::string& filePath, + const CfgParams& cfg_params, + std::shared_ptr selector); + + + GSource(std::shared_ptr source, + const CfgParams& cfg_params = CfgParams{}); + + GSource(std::shared_ptr source, + const CfgParams& cfg_params, + const std::string& device_id, + void* accel_device_ptr, + void* accel_ctx_ptr); + + GSource(std::shared_ptr source, + const CfgParams& cfg_params, + std::shared_ptr selector); + + ~GSource() override; + + bool pull(cv::gapi::wip::Data& data) override; + GMetaArg descr_of() const override; + +private: + explicit GSource(std::unique_ptr&& impl); + std::unique_ptr m_priv; +}; +} // namespace onevpl + +using GVPLSource = onevpl::GSource; + +template +GAPI_EXPORTS_W cv::Ptr inline make_onevpl_src(Args&&... args) +{ + return make_src(std::forward(args)...); +} + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/queue_source.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/queue_source.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bd385ed16e7310bbc54a94589406b70eeeededff --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/queue_source.hpp @@ -0,0 +1,67 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2023 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_QUEUE_SOURCE_HPP +#define OPENCV_GAPI_STREAMING_QUEUE_SOURCE_HPP + +#include // shared_ptr +#include // is_base_of + +#include // GRunArgs +#include // GMetaArg + all descr_of +#include // IStreamSource + +namespace cv { +namespace gapi { +namespace wip { +struct Data; // fwd-declare to avoid circular? header dependencies + +class GAPI_EXPORTS QueueSourceBase: public cv::gapi::wip::IStreamSource { + class Priv; + std::shared_ptr m_priv; + // FIXME: Need to understand how it works with IStreamSource's shared_from_this + // Can we avoid having too many shared_ptrs here? + +public: + explicit QueueSourceBase(const cv::GMetaArg &m); + void push(Data &&data); + virtual bool pull(Data &data) override; + virtual void halt() override; + virtual GMetaArg descr_of() const override; + virtual ~QueueSourceBase() = default; +}; + +/** + * @brief Queued streaming pipeline source. + * + */ +template +class QueueSource final: public QueueSourceBase +{ +public: + using Meta = decltype(cv::descr_of(T{})); + explicit QueueSource(Meta m) : QueueSourceBase(GMetaArg{m}) { + } + void push(T t) { + QueueSourceBase::push(Data{t}); + } +}; + +class GAPI_EXPORTS QueueInput { + std::vector > m_sources; + +public: + explicit QueueInput(const cv::GMetaArgs &args); + + void push(cv::GRunArgs &&ins); + operator cv::GRunArgs(); +}; + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_SOURCE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/source.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/source.hpp new file mode 100644 index 0000000000000000000000000000000000000000..267469ad1b30796217c0bdc034e4981eb31d96bc --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/source.hpp @@ -0,0 +1,67 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2019 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_SOURCE_HPP +#define OPENCV_GAPI_STREAMING_SOURCE_HPP + +#include // shared_ptr +#include // is_base_of + +#include // GMetaArg + + +namespace cv { +namespace gapi { +namespace wip { +struct Data; // forward-declaration of Data to avoid circular dependencies + +/** + * @brief Abstract streaming pipeline source. + * + * Implement this interface if you want customize the way how data is + * streaming into GStreamingCompiled. + * + * Objects implementing this interface can be passed to + * GStreamingCompiled using setSource() with cv::gin(). Regular + * compiled graphs (GCompiled) don't support input objects of this + * type. + * + * Default cv::VideoCapture-based implementation is available, see + * cv::gapi::wip::GCaptureSource. + * + * @note stream sources are passed to G-API via shared pointers, so + * please use ptr() when passing a IStreamSource implementation to + * cv::gin(). + */ +class IStreamSource: public std::enable_shared_from_this +{ +public: + using Ptr = std::shared_ptr; + Ptr ptr() { return shared_from_this(); } + virtual bool pull(Data &data) = 0; + virtual GMetaArg descr_of() const = 0; + virtual void halt() { + // Do nothing by default to maintain compatibility with the existing sources... + // In fact needs to be decorated atop of the child classes to maintain the behavior + // FIXME: Make it mandatory in OpenCV 5.0 + }; + virtual ~IStreamSource() = default; +}; + +template +IStreamSource::Ptr inline make_src(Args&&... args) +{ + static_assert(std::is_base_of::value, + "T must implement the cv::gapi::IStreamSource interface!"); + auto src_ptr = std::make_shared(std::forward(args)...); + return src_ptr->ptr(); +} + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_SOURCE_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/sync.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/sync.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5801e6f00a35d89d0dc627dc31df876b02896a21 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/streaming/sync.hpp @@ -0,0 +1,30 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_SYNC_HPP +#define OPENCV_GAPI_STREAMING_SYNC_HPP + +namespace cv { +namespace gapi { +namespace streaming { + +enum class sync_policy { + dont_sync, + drop +}; + +} // namespace streaming +} // namespace gapi + +namespace detail { + template<> struct CompileArgTag { + static const char* tag() { return "gapi.streaming.sync_policy"; } + }; + +} // namespace detail +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_SYNC_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/any.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/any.hpp new file mode 100644 index 0000000000000000000000000000000000000000..94451c77171750927412064172851eae8b5e13f5 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/any.hpp @@ -0,0 +1,190 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_ANY_HPP +#define OPENCV_GAPI_UTIL_ANY_HPP + +#include +#include +#include +#include + +#include + +#if defined(_MSC_VER) + // disable MSVC warning on "multiple copy constructors specified" +# pragma warning(disable: 4521) +#endif + +namespace cv +{ + +namespace internal +{ + template + T down_cast(Source operand) + { +#if defined(__GXX_RTTI) || defined(_CPPRTTI) + return dynamic_cast(operand); +#else +#ifdef __GNUC__ +#warning used static cast instead of dynamic because RTTI is disabled +#else +#pragma message("WARNING: used static cast instead of dynamic because RTTI is disabled") +#endif + return static_cast(operand); +#endif + } +} + +namespace util +{ + class bad_any_cast : public std::bad_cast + { + public: + virtual const char* what() const noexcept override + { + return "Bad any cast"; + } + }; + + //modeled against C++17 std::any + + class any + { + private: + struct holder; + using holder_ptr = std::unique_ptr; + struct holder + { + virtual holder_ptr clone() = 0; + virtual ~holder() = default; + }; + + template + struct holder_impl : holder + { + value_t v; + template + holder_impl(arg_t&& a) : v(std::forward(a)) {} + holder_ptr clone() override { return holder_ptr(new holder_impl (v));} + }; + + holder_ptr hldr; + public: + template + any(value_t&& arg) : hldr(new holder_impl::type>( std::forward(arg))) {} + + any(any const& src) : hldr( src.hldr ? src.hldr->clone() : nullptr) {} + //simple hack in order not to write enable_if for the template constructor + any(any & src) : any (const_cast(src)) {} + + any() = default; + any(any&& ) = default; + + any& operator=(any&&) = default; + + any& operator=(any const& src) + { + any copy(src); + swap(*this, copy); + return *this; + } + + template + friend value_t* any_cast(any* operand); + + template + friend const value_t* any_cast(const any* operand); + + template + friend value_t& unsafe_any_cast(any& operand); + + template + friend const value_t& unsafe_any_cast(const any& operand); + + friend void swap(any & lhs, any& rhs) + { + swap(lhs.hldr, rhs.hldr); + } + + }; + + template + value_t* any_cast(any* operand) + { + auto casted = internal::down_cast::type> *>(operand->hldr.get()); + if (casted){ + return & (casted->v); + } + return nullptr; + } + + template + const value_t* any_cast(const any* operand) + { + auto casted = internal::down_cast::type> *>(operand->hldr.get()); + if (casted){ + return & (casted->v); + } + return nullptr; + } + + template + value_t& any_cast(any& operand) + { + auto ptr = any_cast(&operand); + if (ptr) + { + return *ptr; + } + + throw_error(bad_any_cast()); + } + + + template + const value_t& any_cast(const any& operand) + { + auto ptr = any_cast(&operand); + if (ptr) + { + return *ptr; + } + + throw_error(bad_any_cast()); + } + + template + inline value_t& unsafe_any_cast(any& operand) + { +#ifdef DEBUG + return any_cast(operand); +#else + return static_cast::type> *>(operand.hldr.get())->v; +#endif + } + + template + inline const value_t& unsafe_any_cast(const any& operand) + { +#ifdef DEBUG + return any_cast(operand); +#else + return static_cast::type> *>(operand.hldr.get())->v; +#endif + } + +} // namespace util +} // namespace cv + +#if defined(_MSC_VER) + // Enable "multiple copy constructors specified" back +# pragma warning(default: 4521) +#endif + +#endif // OPENCV_GAPI_UTIL_ANY_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/compiler_hints.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/compiler_hints.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a41a97145dc75009486e5e2cc51bd798cb265e03 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/compiler_hints.hpp @@ -0,0 +1,19 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + +#ifndef OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP +#define OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP + +namespace cv +{ +namespace util +{ + //! Utility template function to prevent "unused" warnings by various compilers. + template void suppress_unused_warning( const T& ) {} +} // namespace util +} // namespace cv + +#endif /* OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/copy_through_move.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/copy_through_move.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1a1121eb2187de90ea0ce0689089accd6d9ddd44 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/copy_through_move.hpp @@ -0,0 +1,34 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_UTIL_COPY_THROUGH_MOVE_HPP +#define OPENCV_GAPI_UTIL_COPY_THROUGH_MOVE_HPP + +#include //decay_t + +namespace cv +{ +namespace util +{ + //This is a tool to move initialize captures of a lambda in C++11 + template + struct copy_through_move_t{ + T value; + const T& get() const {return value;} + T& get() {return value;} + copy_through_move_t(T&& g) : value(std::move(g)) {} + copy_through_move_t(copy_through_move_t&&) = default; + copy_through_move_t(copy_through_move_t const& lhs) : copy_through_move_t(std::move(const_cast(lhs))) {} + }; + + template + copy_through_move_t> copy_through_move(T&& t){ + return std::forward(t); + } +} // namespace util +} // namespace cv + +#endif /* OPENCV_GAPI_UTIL_COPY_THROUGH_MOVE_HPP */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/optional.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/optional.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dca03cadad86aeec5eb9582597ae13d2dc8607a6 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/optional.hpp @@ -0,0 +1,178 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_OPTIONAL_HPP +#define OPENCV_GAPI_UTIL_OPTIONAL_HPP + +#include + +// A poor man's `optional` implementation, incompletely modeled against C++17 spec. +namespace cv +{ +namespace util +{ + class bad_optional_access: public std::exception + { + public: + virtual const char *what() const noexcept override + { + return "Bad optional access"; + } + }; + + // TODO: nullopt_t + + // Interface /////////////////////////////////////////////////////////////// + template class optional + { + public: + // Constructors + // NB.: there were issues with Clang 3.8 when =default() was used + // instead {} + optional() {} + optional(const optional&) = default; + explicit optional(T&&) noexcept; + explicit optional(const T&) noexcept; + optional(optional&&) noexcept; + // TODO: optional(nullopt_t) noexcept; + // TODO: optional(const optional &) + // TODO: optional(optional &&) + // TODO: optional(Args&&...) + // TODO: optional(initializer_list) + // TODO: optional(U&& value); + + // Assignment + optional& operator=(const optional&) = default; + optional& operator=(optional&&); + + // Observers + T* operator-> (); + const T* operator-> () const; + T& operator* (); + const T& operator* () const; + // TODO: && versions + + operator bool() const noexcept; + bool has_value() const noexcept; + + T& value(); + const T& value() const; + // TODO: && versions + + template + T value_or(U &&default_value) const; + + void swap(optional &other) noexcept; + void reset() noexcept; + // TODO: emplace + + // TODO: operator==, !=, <, <=, >, >= + + private: + struct nothing {}; + util::variant m_holder; + }; + + template + optional::type> make_optional(T&& value); + + // TODO: Args... and initializer_list versions + + // Implementation ////////////////////////////////////////////////////////// + template optional::optional(T &&v) noexcept + : m_holder(std::move(v)) + { + } + + template optional::optional(const T &v) noexcept + : m_holder(v) + { + } + + template optional::optional(optional&& rhs) noexcept + : m_holder(std::move(rhs.m_holder)) + { + rhs.reset(); + } + + template optional& optional::operator=(optional&& rhs) + { + m_holder = std::move(rhs.m_holder); + rhs.reset(); + return *this; + } + + template T* optional::operator-> () + { + return & *(*this); + } + + template const T* optional::operator-> () const + { + return & *(*this); + } + + template T& optional::operator* () + { + return this->value(); + } + + template const T& optional::operator* () const + { + return this->value(); + } + + template optional::operator bool() const noexcept + { + return this->has_value(); + } + + template bool optional::has_value() const noexcept + { + return util::holds_alternative(m_holder); + } + + template T& optional::value() + { + if (!this->has_value()) + throw_error(bad_optional_access()); + return util::get(m_holder); + } + + template const T& optional::value() const + { + if (!this->has_value()) + throw_error(bad_optional_access()); + return util::get(m_holder); + } + + template + template T optional::value_or(U &&default_value) const + { + return (this->has_value() ? this->value() : T(default_value)); + } + + template void optional::swap(optional &other) noexcept + { + m_holder.swap(other.m_holder); + } + + template void optional::reset() noexcept + { + if (this->has_value()) + m_holder = nothing{}; + } + + template + optional::type> make_optional(T&& value) + { + return optional::type>(std::forward(value)); + } +} // namespace util +} // namespace cv + +#endif // OPENCV_GAPI_UTIL_OPTIONAL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/throw.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/throw.hpp new file mode 100644 index 0000000000000000000000000000000000000000..689bf583cfee9ef25b4e45bbbe96d641b56db9a1 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/throw.hpp @@ -0,0 +1,36 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_THROW_HPP +#define OPENCV_GAPI_UTIL_THROW_HPP + +#include // std::forward + +#if !defined(__EXCEPTIONS) +#include +#include +#endif + +namespace cv +{ +namespace util +{ +template +[[noreturn]] void throw_error(ExceptionType &&e) +{ +#if defined(__EXCEPTIONS) || defined(_CPPUNWIND) + throw std::forward(e); +#else + fprintf(stderr, "An exception thrown! %s\n" , e.what()); + fflush(stderr); + abort(); +#endif +} +} // namespace util +} // namespace cv + +#endif // OPENCV_GAPI_UTIL_THROW_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/type_traits.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/type_traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..637f18460bcdbea97bded61166a4c1173f5105df --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/type_traits.hpp @@ -0,0 +1,31 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP +#define OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP + +#include + +namespace cv +{ +namespace util +{ + //these are C++14 parts of type_traits : + template< bool B, class T = void > + using enable_if_t = typename std::enable_if::type; + + template + using decay_t = typename std::decay::type; + + //this is not part of C++14 but still, of pretty common usage + template + using are_different_t = enable_if_t< !std::is_same, decay_t>::value, V>; + +} // namespace cv +} // namespace util + +#endif // OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/util.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/util.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3be46d7ec2e8563ca8d2acfec6aef59416f9e471 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/util.hpp @@ -0,0 +1,190 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018-2019 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_HPP +#define OPENCV_GAPI_UTIL_HPP + +#include + +// \cond HIDDEN_SYMBOLS +// This header file contains some generic utility functions which are +// used in other G-API Public API headers. +// +// PLEASE don't put any stuff here if it is NOT used in public API headers! + +namespace cv +{ +namespace detail +{ + // Recursive integer sequence type, useful for enumerating elements of + // template parameter packs. + template struct Seq { using next = Seq; }; + template struct MkSeq { using type = typename MkSeq::type::next; }; + template<> struct MkSeq<0>{ using type = Seq<>; }; + + // Checks if elements of variadic template satisfy the given Predicate. + // Implemented via tuple, with an interface to accept plain type lists + template class, typename, typename...> struct all_satisfy; + + template class F, typename T, typename... Ts> + struct all_satisfy > + { + static const constexpr bool value = F::value + && all_satisfy >::value; + }; + template class F, typename T> + struct all_satisfy > + { + static const constexpr bool value = F::value; + }; + + template class F, typename T, typename... Ts> + struct all_satisfy: public all_satisfy > {}; + + // Permute given tuple type C with given integer sequence II + // Sequence may be less than tuple C size. + template struct permute_tuple; + + template + struct permute_tuple > + { + using type = std::tuple< typename std::tuple_element::type... >; + }; + + // Given T..., generates a type sequence of sizeof...(T)-1 elements + // which is T... without its last element + // Implemented via tuple, with an interface to accept plain type lists + template struct all_but_last; + + template + struct all_but_last > + { + using C = std::tuple; + using S = typename MkSeq::value - 1>::type; + using type = typename permute_tuple::type; + }; + + template + struct all_but_last: public all_but_last > {}; + + template + using all_but_last_t = typename all_but_last::type; + + // NB.: This is here because there's no constexpr std::max in C++11 + template struct max_of_t + { + static constexpr const std::size_t rest = max_of_t::value; + static constexpr const std::size_t value = rest > S0 ? rest : S0; + }; + template struct max_of_t + { + static constexpr const std::size_t value = S; + }; + + template + struct contains : std::false_type{}; + + template + struct contains : std::integral_constant::value || + contains::value> {}; + template + struct contains> : std::integral_constant::value> {}; + + template + struct all_unique : std::true_type{}; + + template + struct all_unique : std::integral_constant::value && + all_unique::value> {}; + + template + struct tuple_wrap_helper; + + template struct tuple_wrap_helper + { + using type = std::tuple; + static type get(T&& obj) { return std::make_tuple(std::move(obj)); } + }; + + template + struct tuple_wrap_helper> + { + using type = std::tuple; + static type get(std::tuple&& objs) { return std::forward>(objs); } + }; + + template + struct make_void { typedef void type;}; + + template + using void_t = typename make_void::type; + +} // namespace detail + +namespace util +{ +template +struct overload_lamba_set; + +template +struct overload_lamba_set : public L1 +{ + overload_lamba_set(L1&& lambda) : L1(std::move(lambda)) {} + overload_lamba_set(const L1& lambda) : L1(lambda) {} + + using L1::operator(); +}; + +template +struct overload_lamba_set : public L1, public overload_lamba_set +{ + using base_type = overload_lamba_set; + overload_lamba_set(L1 &&lambda1, L&& ...lambdas): + L1(std::move(lambda1)), + base_type(std::forward(lambdas)...) {} + + overload_lamba_set(const L1 &lambda1, L&& ...lambdas): + L1(lambda1), + base_type(std::forward(lambdas)...) {} + + using L1::operator(); + using base_type::operator(); +}; + +template +overload_lamba_set overload_lambdas(L&& ...lambdas) +{ + return overload_lamba_set(std::forward(lambdas)...); +} + +template +struct find_adapter_impl; + +template +struct find_adapter_impl +{ + using type = typename std::conditional::value, + T, + void>::type; + static constexpr bool found = std::is_base_of::value; +}; + +template +struct find_adapter_impl +{ + using type = typename std::conditional::value, + T, + typename find_adapter_impl::type>::type; + static constexpr bool found = std::is_base_of::value || + find_adapter_impl::found; +}; +} // namespace util +} // namespace cv + +// \endcond + +#endif // OPENCV_GAPI_UTIL_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/variant.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/variant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..48b55646c53dec3855d8860984b2847f618eb99d --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/util/variant.hpp @@ -0,0 +1,667 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2018 Intel Corporation + + +#ifndef OPENCV_GAPI_UTIL_VARIANT_HPP +#define OPENCV_GAPI_UTIL_VARIANT_HPP + +#include +#include + +#include +#include +#include // max_of_t +#include + +// A poor man's `variant` implementation, incompletely modeled against C++17 spec. +namespace cv +{ +namespace util +{ + namespace detail + { + template + struct type_list_index_helper + { + static const constexpr bool is_same = std::is_same::value; + static const constexpr std::size_t value = + std::conditional, type_list_index_helper>::type::value; + }; + + template + struct type_list_index_helper + { + static_assert(std::is_same::value, "Type not found"); + static const constexpr std::size_t value = I; + }; + } + + template + struct type_list_index + { + static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value; + }; + + template + struct type_list_element + { + using type = typename std::tuple_element >::type; + }; + + class bad_variant_access: public std::exception + { + public: + virtual const char *what() const noexcept override + { + return "Bad variant access"; + } + }; + + // Interface /////////////////////////////////////////////////////////////// + struct monostate {}; + inline bool operator==(const util::monostate&, const util::monostate&) + { + return true; + } + + template // FIXME: no references, arrays, and void + class variant + { + // FIXME: Replace with std::aligned_union after gcc4.8 support is dropped + static constexpr const std::size_t S = cv::detail::max_of_t::value; + static constexpr const std::size_t A = cv::detail::max_of_t::value; + using Memory = typename std::aligned_storage::type[1]; + + template struct cctr_h { + static void help(Memory memory, const Memory from) { + new (memory) T(*reinterpret_cast(from)); + } + }; + + template struct mctr_h { + static void help(Memory memory, void *pval) { + new (memory) T(std::move(*reinterpret_cast(pval))); + } + }; + + //FIXME: unify with cctr_h and mctr_h + template struct cnvrt_ctor_h { + static void help(Memory memory, void* from) { + using util::decay_t; + new (memory) decay_t(std::forward(*reinterpret_cast*>(from))); + } + }; + + template struct copy_h { + static void help(Memory to, const Memory from) { + *reinterpret_cast(to) = *reinterpret_cast(from); + } + }; + + template struct move_h { + static void help(Memory to, Memory from) { + *reinterpret_cast(to) = std::move(*reinterpret_cast(from)); + } + }; + + //FIXME: unify with copy_h and move_h + template struct cnvrt_assign_h { + static void help(Memory to, void* from) { + using util::decay_t; + *reinterpret_cast*>(to) = std::forward(*reinterpret_cast*>(from)); + } + }; + + template struct swap_h { + static void help(Memory to, Memory from) { + std::swap(*reinterpret_cast(to), *reinterpret_cast(from)); + } + }; + + template struct dtor_h { + static void help(Memory memory) { + (void) memory; // MSCV warning + reinterpret_cast(memory)->~T(); + } + }; + + template struct equal_h { + static bool help(const Memory lhs, const Memory rhs) { + const T& t_lhs = *reinterpret_cast(lhs); + const T& t_rhs = *reinterpret_cast(rhs); + return t_lhs == t_rhs; + } + }; + + typedef void (*CCtr) (Memory, const Memory); // Copy c-tor (variant) + typedef void (*MCtr) (Memory, void*); // Generic move c-tor + typedef void (*Copy) (Memory, const Memory); // Copy assignment + typedef void (*Move) (Memory, Memory); // Move assignment + + typedef void (*Swap) (Memory, Memory); // Swap + typedef void (*Dtor) (Memory); // Destructor + + using cnvrt_assgn_t = void (*) (Memory, void*); // Converting assignment (via std::forward) + using cnvrt_ctor_t = void (*) (Memory, void*); // Converting constructor (via std::forward) + + typedef bool (*Equal)(const Memory, const Memory); // Equality test (external) + + static constexpr std::array cctrs(){ return {{(&cctr_h::help)...}};} + static constexpr std::array mctrs(){ return {{(&mctr_h::help)...}};} + static constexpr std::array cpyrs(){ return {{(©_h::help)...}};} + static constexpr std::array mvers(){ return {{(&move_h::help)...}};} + static constexpr std::array swprs(){ return {{(&swap_h::help)...}};} + static constexpr std::array dtors(){ return {{(&dtor_h::help)...}};} + + template + struct conditional_ref : std::conditional::type&, typename std::remove_reference::type > {}; + + template + using conditional_ref_t = typename conditional_ref::type; + + + template + static constexpr std::array cnvrt_assgnrs(){ + return {{(&cnvrt_assign_h>::help)...}}; + } + + template + static constexpr std::array cnvrt_ctors(){ + return {{(&cnvrt_ctor_h>::help)...}}; + } + + std::size_t m_index = 0; + + protected: + template friend T& get(variant &v); + template friend const T& get(const variant &v); + template friend T* get_if(variant *v) noexcept; + template friend const T* get_if(const variant *v) noexcept; + + template friend bool operator==(const variant &lhs, + const variant &rhs); + Memory memory; + + public: + // Constructors + variant() noexcept; + variant(const variant& other); + variant(variant&& other) noexcept; + // are_different_t is a SFINAE trick to avoid variant(T &&t) with T=variant + // for some reason, this version is called instead of variant(variant&& o) when + // variant is used in STL containers (examples: vector assignment). + template< + typename T, + typename = util::are_different_t + > + explicit variant(T&& t); + // template explicit variant(Args&&... args); + // FIXME: other constructors + + // Destructor + ~variant(); + + // Assignment + variant& operator=(const variant& rhs); + variant& operator=(variant &&rhs) noexcept; + + // SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above + template< + typename T, + typename = util::are_different_t + > + variant& operator=(T&& t) noexcept; + + // Observers + std::size_t index() const noexcept; + // FIXME: valueless_by_exception() + + // Modifiers + // FIXME: emplace() + void swap(variant &rhs) noexcept; + + // Non-C++17x! + template static constexpr std::size_t index_of(); + }; + + // FIMXE: visit + template + T* get_if(util::variant* v) noexcept; + + template + const T* get_if(const util::variant* v) noexcept; + + template + T& get(util::variant &v); + + template + const T& get(const util::variant &v); + + template + typename util::type_list_element::type& get(util::variant &v); + + template + const typename util::type_list_element::type& get(const util::variant &v); + + template + bool holds_alternative(const util::variant &v) noexcept; + + + // Visitor + namespace detail + { + struct visitor_interface {}; + + // Class `visitor_return_type_deduction_helper` + // introduces solution for deduction `return_type` in `visit` function in common way + // for both Lambda and class Visitor and keep one interface invocation point: `visit` only + // his helper class is required to unify return_type deduction mechanism because + // for Lambda it is possible to take type of `decltype(visitor(get<0>(var)))` + // but for class Visitor there is no operator() in base case, + // because it provides `operator() (std::size_t index, ...)` + // So `visitor_return_type_deduction_helper` expose `operator()` + // uses only for class Visitor only for deduction `return type` in visit() + template + struct visitor_return_type_deduction_helper + { + using return_type = R; + + // to be used in Lambda return type deduction context only + template + return_type operator() (T&&); + }; + } + + // Special purpose `static_visitor` can receive additional arguments + template + struct static_visitor : public detail::visitor_interface, + public detail::visitor_return_type_deduction_helper { + + // assign responsibility for return type deduction to helper class + using return_type = typename detail::visitor_return_type_deduction_helper::return_type; + using detail::visitor_return_type_deduction_helper::operator(); + friend Impl; + + template + return_type operator() (std::size_t index, VariantValue&& value, Args&& ...args) + { + suppress_unused_warning(index); + return static_cast(this)-> visit( + std::forward(value), + std::forward(args)...); + } + }; + + // Special purpose `static_indexed_visitor` can receive additional arguments + // And make forwarding current variant index as runtime function argument to its `Impl` + template + struct static_indexed_visitor : public detail::visitor_interface, + public detail::visitor_return_type_deduction_helper { + + // assign responsibility for return type deduction to helper class + using return_type = typename detail::visitor_return_type_deduction_helper::return_type; + using detail::visitor_return_type_deduction_helper::operator(); + friend Impl; + + template + return_type operator() (std::size_t Index, VariantValue&& value, Args&& ...args) + { + return static_cast(this)-> visit(Index, + std::forward(value), + std::forward(args)...); + } + }; + + template + struct variant_size; + + template + struct variant_size> + : std::integral_constant { }; + // FIXME: T&&, const TT&& versions. + + // Implementation ////////////////////////////////////////////////////////// + template + variant::variant() noexcept + { + typedef typename std::tuple_element<0, std::tuple >::type TFirst; + new (memory) TFirst(); + } + + template + variant::variant(const variant &other) + : m_index(other.m_index) + { + (cctrs()[m_index])(memory, other.memory); + } + + template + variant::variant(variant &&other) noexcept + : m_index(other.m_index) + { + (mctrs()[m_index])(memory, other.memory); + } + + template + template + variant::variant(T&& t) + : m_index(util::type_list_index, Ts...>::value) + { + const constexpr bool is_lvalue_arg = std::is_lvalue_reference::value; + (cnvrt_ctors()[m_index])(memory, const_cast *>(&t)); + } + + template + variant::~variant() + { + (dtors()[m_index])(memory); + } + + template + variant& variant::operator=(const variant &rhs) + { + if (m_index != rhs.m_index) + { + (dtors()[ m_index])(memory); + (cctrs()[rhs.m_index])(memory, rhs.memory); + m_index = rhs.m_index; + } + else + { + (cpyrs()[rhs.m_index])(memory, rhs.memory); + } + return *this; + } + + template + variant& variant::operator=(variant &&rhs) noexcept + { + if (m_index != rhs.m_index) + { + (dtors()[ m_index])(memory); + (mctrs()[rhs.m_index])(memory, rhs.memory); + m_index = rhs.m_index; + } + else + { + (mvers()[rhs.m_index])(memory, rhs.memory); + } + return *this; + } + + template + template + variant& variant::operator=(T&& t) noexcept + { + using decayed_t = util::decay_t; + // FIXME: No version with implicit type conversion available! + const constexpr std::size_t t_index = + util::type_list_index::value; + + const constexpr bool is_lvalue_arg = std::is_lvalue_reference::value; + + if (t_index != m_index) + { + (dtors()[m_index])(memory); + (cnvrt_ctors()[t_index])(memory, &t); + m_index = t_index; + } + else + { + (cnvrt_assgnrs()[m_index])(memory, &t); + } + return *this; + + } + + template + std::size_t util::variant::index() const noexcept + { + return m_index; + } + + template + void variant::swap(variant &rhs) noexcept + { + if (m_index == rhs.index()) + { + (swprs()[m_index](memory, rhs.memory)); + } + else + { + variant tmp(std::move(*this)); + *this = std::move(rhs); + rhs = std::move(tmp); + } + } + + template + template + constexpr std::size_t variant::index_of() + { + return util::type_list_index::value; // FIXME: tests! + } + + template + T* get_if(util::variant* v) noexcept + { + const constexpr std::size_t t_index = + util::type_list_index::value; + + if (v && v->index() == t_index) + return (T*)(&v->memory); // workaround for ICC 2019 + // original code: return reinterpret_cast(v.memory); + return nullptr; + } + + template + const T* get_if(const util::variant* v) noexcept + { + const constexpr std::size_t t_index = + util::type_list_index::value; + + if (v && v->index() == t_index) + return (const T*)(&v->memory); // workaround for ICC 2019 + // original code: return reinterpret_cast(v.memory); + return nullptr; + } + + template + T& get(util::variant &v) + { + if (auto* p = get_if(&v)) + return *p; + else + throw_error(bad_variant_access()); + } + + template + const T& get(const util::variant &v) + { + if (auto* p = get_if(&v)) + return *p; + else + throw_error(bad_variant_access()); + } + + template + typename util::type_list_element::type& get(util::variant &v) + { + using ReturnType = typename util::type_list_element::type; + return const_cast(get(static_cast &>(v))); + } + + template + const typename util::type_list_element::type& get(const util::variant &v) + { + static_assert(Index < sizeof...(Types), + "`Index` it out of bound of `util::variant` type list"); + using ReturnType = typename util::type_list_element::type; + return get(v); + } + + template + bool holds_alternative(const util::variant &v) noexcept + { + return v.index() == util::variant::template index_of(); + } + +#if defined(__GNUC__) && (__GNUC__ == 11 || __GNUC__ == 12) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + + template bool operator==(const variant &lhs, + const variant &rhs) + { + using V = variant; + + // Instantiate table only here since it requires operator== for + // should have operator== only if this one is used, not in general + static const std::array eqs = { + {(&V::template equal_h::help)...} + }; + if (lhs.index() != rhs.index()) + return false; + return (eqs[lhs.index()])(lhs.memory, rhs.memory); + } + +#if defined(__GNUC__) && (__GNUC__ == 11 || __GNUC__ == 12) +#pragma GCC diagnostic pop +#endif + + template bool operator!=(const variant &lhs, + const variant &rhs) + { + return !(lhs == rhs); + } + +namespace detail +{ + // terminate recursion implementation for `non-void` ReturnType + template + ReturnType apply_visitor_impl(Visitor&&, Variant&, + std::true_type, std::false_type, + VisitorArgs&& ...) + { + return {}; + } + + // terminate recursion implementation for `void` ReturnType + template + void apply_visitor_impl(Visitor&&, Variant&, + std::true_type, std::true_type, + VisitorArgs&& ...) + { + } + + // Intermediate resursion processor for Lambda Visitors + template + typename std::enable_if::type>::value, ReturnType>::type + apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed, + std::integral_constant should_no_return, + VisitorArgs&& ...args) + { + static_assert(std::is_same(v)))>::value, + "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`" + " must return the same type"); + suppress_unused_warning(not_processed); + if (v.index() == CurIndex) + { + return visitor.operator()(get(v), std::forward(args)... ); + } + + using is_variant_processed_t = std::integral_constant= ElemCount>; + return apply_visitor_impl( + std::forward(visitor), + std::forward(v), + is_variant_processed_t{}, + should_no_return, + std::forward(args)...); + } + + //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator() + template + typename std::enable_if::type>, + typename std::decay::type>::value, ReturnType>::type + invoke_class_visitor(Visitor& visitor, Value&& v, VisitorArgs&&...args) + { + return static_cast::type>&>(visitor).operator() (CurIndex, std::forward(v), std::forward(args)... ); + } + + //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator() + template + typename std::enable_if::type>, + typename std::decay::type>::value, ReturnType>::type + invoke_class_visitor(Visitor& visitor, Value&& v, VisitorArgs&&...args) + { + return static_cast::type>&>(visitor).operator() (CurIndex, std::forward(v), std::forward(args)... ); + } + + // Intermediate recursion processor for special case `visitor_interface` derived Visitors + template + typename std::enable_if::type>::value, ReturnType>::type + apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed, + std::integral_constant should_no_return, + VisitorArgs&& ...args) + { + static_assert(std::is_same(v)))>::value, + "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`" + " must return the same type"); + suppress_unused_warning(not_processed); + if (v.index() == CurIndex) + { + return invoke_class_visitor(visitor, get(v), std::forward(args)... ); + } + + using is_variant_processed_t = std::integral_constant= ElemCount>; + return apply_visitor_impl( + std::forward(visitor), + std::forward(v), + is_variant_processed_t{}, + should_no_return, + std::forward(args)...); + } +} // namespace detail + + template + auto visit(Visitor &visitor, const Variant& var, VisitorArg &&...args) -> decltype(visitor(get<0>(var))) + { + constexpr std::size_t varsize = util::variant_size::value; + static_assert(varsize != 0, "utils::variant must contains one type at least "); + using is_variant_processed_t = std::false_type; + + using ReturnType = decltype(visitor(get<0>(var))); + using return_t = std::is_same; + return detail::apply_visitor_impl( + std::forward(visitor), + var, is_variant_processed_t{}, + return_t{}, + std::forward(args)...); + } + + template + auto visit(Visitor&& visitor, const Variant& var) -> decltype(visitor(get<0>(var))) + { + constexpr std::size_t varsize = util::variant_size::value; + static_assert(varsize != 0, "utils::variant must contains one type at least "); + using is_variant_processed_t = std::false_type; + + using ReturnType = decltype(visitor(get<0>(var))); + using return_t = std::is_same; + return detail::apply_visitor_impl( + std::forward(visitor), + var, is_variant_processed_t{}, + return_t{}); + } +} // namespace util +} // namespace cv + +#endif // OPENCV_GAPI_UTIL_VARIANT_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/video.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/video.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4dcc1d4182410b1e8ba3d672652ad5a3be31ced6 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/gapi/video.hpp @@ -0,0 +1,364 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_VIDEO_HPP +#define OPENCV_GAPI_VIDEO_HPP + +#include // std::tuple + +#include + + +/** \defgroup gapi_video G-API Video processing functionality + */ + +namespace cv { namespace gapi { + +/** @brief Structure for the Kalman filter's initialization parameters.*/ + +struct GAPI_EXPORTS KalmanParams +{ + // initial state + + //! corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) + Mat state; + //! posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) + Mat errorCov; + + // dynamic system description + + //! state transition matrix (A) + Mat transitionMatrix; + //! measurement matrix (H) + Mat measurementMatrix; + //! process noise covariance matrix (Q) + Mat processNoiseCov; + //! measurement noise covariance matrix (R) + Mat measurementNoiseCov; + //! control matrix (B) (Optional: not used if there's no control) + Mat controlMatrix; +}; + +/** + * @brief This namespace contains G-API Operations and functions for + * video-oriented algorithms, like optical flow and background subtraction. + */ +namespace video +{ +using GBuildPyrOutput = std::tuple, GScalar>; + +using GOptFlowLKOutput = std::tuple, + cv::GArray, + cv::GArray>; + +G_TYPED_KERNEL(GBuildOptFlowPyramid, , + "org.opencv.video.buildOpticalFlowPyramid") +{ + static std::tuple + outMeta(GMatDesc,const Size&,GScalarDesc,bool,int,int,bool) + { + return std::make_tuple(empty_array_desc(), empty_scalar_desc()); + } +}; + +G_TYPED_KERNEL(GCalcOptFlowLK, + ,cv::GArray,Size, + GScalar,TermCriteria,int,double)>, + "org.opencv.video.calcOpticalFlowPyrLK") +{ + static std::tuple outMeta(GMatDesc,GMatDesc,GArrayDesc, + GArrayDesc,const Size&,GScalarDesc, + const TermCriteria&,int,double) + { + return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc()); + } + +}; + +G_TYPED_KERNEL(GCalcOptFlowLKForPyr, + ,cv::GArray, + cv::GArray,cv::GArray,Size,GScalar, + TermCriteria,int,double)>, + "org.opencv.video.calcOpticalFlowPyrLKForPyr") +{ + static std::tuple outMeta(GArrayDesc,GArrayDesc, + GArrayDesc,GArrayDesc, + const Size&,GScalarDesc, + const TermCriteria&,int,double) + { + return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc()); + } +}; + +enum BackgroundSubtractorType +{ + TYPE_BS_MOG2, + TYPE_BS_KNN +}; + +/** @brief Structure for the Background Subtractor operation's initialization parameters.*/ + +struct BackgroundSubtractorParams +{ + //! Type of the Background Subtractor operation. + BackgroundSubtractorType operation = TYPE_BS_MOG2; + + //! Length of the history. + int history = 500; + + //! For MOG2: Threshold on the squared Mahalanobis distance between the pixel + //! and the model to decide whether a pixel is well described by + //! the background model. + //! For KNN: Threshold on the squared distance between the pixel and the sample + //! to decide whether a pixel is close to that sample. + double threshold = 16; + + //! If true, the algorithm will detect shadows and mark them. + bool detectShadows = true; + + //! The value between 0 and 1 that indicates how fast + //! the background model is learnt. + //! Negative parameter value makes the algorithm use some automatically + //! chosen learning rate. + double learningRate = -1; + + //! default constructor + BackgroundSubtractorParams() {} + + /** Full constructor + @param op MOG2/KNN Background Subtractor type. + @param histLength Length of the history. + @param thrshld For MOG2: Threshold on the squared Mahalanobis distance between + the pixel and the model to decide whether a pixel is well described by the background model. + For KNN: Threshold on the squared distance between the pixel and the sample to decide + whether a pixel is close to that sample. + @param detect If true, the algorithm will detect shadows and mark them. It decreases the + speed a bit, so if you do not need this feature, set the parameter to false. + @param lRate The value between 0 and 1 that indicates how fast the background model is learnt. + Negative parameter value makes the algorithm to use some automatically chosen learning rate. + */ + BackgroundSubtractorParams(BackgroundSubtractorType op, int histLength, + double thrshld, bool detect, double lRate) : operation(op), + history(histLength), + threshold(thrshld), + detectShadows(detect), + learningRate(lRate){} +}; + +G_TYPED_KERNEL(GBackgroundSubtractor, , + "org.opencv.video.BackgroundSubtractor") +{ + static GMatDesc outMeta(const GMatDesc& in, const BackgroundSubtractorParams& bsParams) + { + GAPI_Assert(bsParams.history >= 0); + GAPI_Assert(bsParams.learningRate <= 1); + return in.withType(CV_8U, 1); + } +}; + +void checkParams(const cv::gapi::KalmanParams& kfParams, + const cv::GMatDesc& measurement, const cv::GMatDesc& control = {}); + +G_TYPED_KERNEL(GKalmanFilter, , GMat, KalmanParams)>, + "org.opencv.video.KalmanFilter") +{ + static GMatDesc outMeta(const GMatDesc& measurement, const GOpaqueDesc&, + const GMatDesc& control, const KalmanParams& kfParams) + { + checkParams(kfParams, measurement, control); + return measurement.withSize(Size(1, kfParams.transitionMatrix.rows)); + } +}; + +G_TYPED_KERNEL(GKalmanFilterNoControl, , KalmanParams)>, "org.opencv.video.KalmanFilterNoControl") +{ + static GMatDesc outMeta(const GMatDesc& measurement, const GOpaqueDesc&, const KalmanParams& kfParams) + { + checkParams(kfParams, measurement); + return measurement.withSize(Size(1, kfParams.transitionMatrix.rows)); + } +}; +} //namespace video + +//! @addtogroup gapi_video +//! @{ +/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK. + +@note Function textual ID is "org.opencv.video.buildOpticalFlowPyramid" + +@param img 8-bit input image. +@param winSize window size of optical flow algorithm. Must be not less than winSize + argument of calcOpticalFlowPyrLK. It is needed to calculate required + padding for pyramid levels. +@param maxLevel 0-based maximal pyramid level number. +@param withDerivatives set to precompute gradients for the every pyramid level. If pyramid is + constructed without the gradients then calcOpticalFlowPyrLK will calculate + them internally. +@param pyrBorder the border mode for pyramid layers. +@param derivBorder the border mode for gradients. +@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false + to force data copying. + +@return + - output pyramid. + - number of levels in constructed pyramid. Can be less than maxLevel. + */ +GAPI_EXPORTS std::tuple, GScalar> +buildOpticalFlowPyramid(const GMat &img, + const Size &winSize, + const GScalar &maxLevel, + bool withDerivatives = true, + int pyrBorder = BORDER_REFLECT_101, + int derivBorder = BORDER_CONSTANT, + bool tryReuseInputImage = true); + +/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade +method with pyramids. + +See @cite Bouguet00 . + +@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLK" + +@param prevImg first 8-bit input image (GMat) or pyramid (GArray) constructed by +buildOpticalFlowPyramid. +@param nextImg second input image (GMat) or pyramid (GArray) of the same size and the same +type as prevImg. +@param prevPts GArray of 2D points for which the flow needs to be found; point coordinates must be +single-precision floating-point numbers. +@param predPts GArray of 2D points initial for the flow search; make sense only when +OPTFLOW_USE_INITIAL_FLOW flag is passed; in that case the vector must have the same size as in +the input. +@param winSize size of the search window at each pyramid level. +@param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single +level), if set to 1, two levels are used, and so on; if pyramids are passed to input then +algorithm will use as many levels as pyramids have but no more than maxLevel. +@param criteria parameter, specifying the termination criteria of the iterative search algorithm +(after the specified maximum number of iterations criteria.maxCount or when the search window +moves by less than criteria.epsilon). +@param flags operation flags: + - **OPTFLOW_USE_INITIAL_FLOW** uses initial estimations, stored in nextPts; if the flag is + not set, then prevPts is copied to nextPts and is considered the initial estimate. + - **OPTFLOW_LK_GET_MIN_EIGENVALS** use minimum eigen values as an error measure (see + minEigThreshold description); if the flag is not set, then L1 distance between patches + around the original and a moved point, divided by number of pixels in a window, is used as a + error measure. +@param minEigThresh the algorithm calculates the minimum eigen value of a 2x2 normal matrix of +optical flow equations (this matrix is called a spatial gradient matrix in @cite Bouguet00), divided +by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding +feature is filtered out and its flow is not processed, so it allows to remove bad points and get a +performance boost. + +@return + - GArray of 2D points (with single-precision floating-point coordinates) +containing the calculated new positions of input features in the second image. + - status GArray (of unsigned chars); each element of the vector is set to 1 if +the flow for the corresponding features has been found, otherwise, it is set to 0. + - GArray of errors (doubles); each element of the vector is set to an error for the +corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't +found then the error is not defined (use the status parameter to find such cases). + */ +GAPI_EXPORTS std::tuple, GArray, GArray> +calcOpticalFlowPyrLK(const GMat &prevImg, + const GMat &nextImg, + const GArray &prevPts, + const GArray &predPts, + const Size &winSize = Size(21, 21), + const GScalar &maxLevel = 3, + const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT | + TermCriteria::EPS, + 30, 0.01), + int flags = 0, + double minEigThresh = 1e-4); + +/** +@overload +@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLKForPyr" +*/ +GAPI_EXPORTS std::tuple, GArray, GArray> +calcOpticalFlowPyrLK(const GArray &prevPyr, + const GArray &nextPyr, + const GArray &prevPts, + const GArray &predPts, + const Size &winSize = Size(21, 21), + const GScalar &maxLevel = 3, + const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT | + TermCriteria::EPS, + 30, 0.01), + int flags = 0, + double minEigThresh = 1e-4); + +/** @brief Gaussian Mixture-based or K-nearest neighbours-based Background/Foreground Segmentation Algorithm. +The operation generates a foreground mask. + +@return Output image is foreground mask, i.e. 8-bit unsigned 1-channel (binary) matrix @ref CV_8UC1. + +@note Functional textual ID is "org.opencv.video.BackgroundSubtractor" + +@param src input image: Floating point frame is used without scaling and should be in range [0,255]. +@param bsParams Set of initialization parameters for Background Subtractor kernel. +*/ +GAPI_EXPORTS GMat BackgroundSubtractor(const GMat& src, const cv::gapi::video::BackgroundSubtractorParams& bsParams); + +/** @brief Standard Kalman filter algorithm . + +@note Functional textual ID is "org.opencv.video.KalmanFilter" + +@param measurement input matrix: 32-bit or 64-bit float 1-channel matrix containing measurements. +@param haveMeasurement dynamic input flag that indicates whether we get measurements +at a particular iteration . +@param control input matrix: 32-bit or 64-bit float 1-channel matrix contains control data +for changing dynamic system. +@param kfParams Set of initialization parameters for Kalman filter kernel. + +@return Output matrix is predicted or corrected state. They can be 32-bit or 64-bit float +1-channel matrix @ref CV_32FC1 or @ref CV_64FC1. + +@details If measurement matrix is given (haveMeasurements == true), corrected state will +be returned which corresponds to the pipeline +cv::KalmanFilter::predict(control) -> cv::KalmanFilter::correct(measurement). +Otherwise, predicted state will be returned which corresponds to the call of +cv::KalmanFilter::predict(control). +@sa cv::KalmanFilter +*/ +GAPI_EXPORTS GMat KalmanFilter(const GMat& measurement, const GOpaque& haveMeasurement, + const GMat& control, const cv::gapi::KalmanParams& kfParams); + +/** @overload +The case of Standard Kalman filter algorithm when there is no control in a dynamic system. +In this case the controlMatrix is empty and control vector is absent. + +@note Function textual ID is "org.opencv.video.KalmanFilterNoControl" + +@param measurement input matrix: 32-bit or 64-bit float 1-channel matrix containing measurements. +@param haveMeasurement dynamic input flag that indicates whether we get measurements +at a particular iteration. +@param kfParams Set of initialization parameters for Kalman filter kernel. + +@return Output matrix is predicted or corrected state. They can be 32-bit or 64-bit float +1-channel matrix @ref CV_32FC1 or @ref CV_64FC1. + +@sa cv::KalmanFilter + */ +GAPI_EXPORTS GMat KalmanFilter(const GMat& measurement, const GOpaque& haveMeasurement, + const cv::gapi::KalmanParams& kfParams); + +//! @} gapi_video +} //namespace gapi +} //namespace cv + + +namespace cv { namespace detail { +template<> struct CompileArgTag +{ + static const char* tag() + { + return "org.opencv.video.background_substractor_params"; + } +}; +} // namespace detail +} // namespace cv + +#endif // OPENCV_GAPI_VIDEO_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgcodecs.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgcodecs.hpp index 2aeac8d60a7d7234e81281a1d23d69ce815a9599..cd648c2c6e6975aa2557e0e1b3303b899c920f2e 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgcodecs.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgcodecs.hpp @@ -65,7 +65,6 @@ namespace cv //! @{ //! Imread flags -//! @note IMREAD_COLOR_BGR (IMREAD_COLOR) and IMREAD_COLOR_RGB can not be set at the same time. enum ImreadModes { IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation. IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion). @@ -94,10 +93,8 @@ enum ImwriteFlags { IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is -1 - don't use. If JPEG_LIB_VERSION < 70, Not supported. IMWRITE_JPEG_SAMPLING_FACTOR = 7, //!< For JPEG, set sampling factor. See cv::ImwriteJPEGSamplingFactorParams. IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting). - IMWRITE_PNG_STRATEGY = 17, //!< For PNG, One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. - IMWRITE_PNG_BILEVEL = 18, //!< For PNG, Binary level PNG, 0 or 1, default is 0. - IMWRITE_PNG_FILTER = 19, //!< For PNG, One of cv::ImwritePNGFilterFlags, default is IMWRITE_PNG_FILTER_SUB. - IMWRITE_PNG_ZLIBBUFFER_SIZE = 20, //!< For PNG with libpng, sets the size of the internal zlib compression buffer in bytes, from 6 to 1048576(1024 KiB). Default is 8192(8 KiB). For normal use, 131072(128 KiB) or 262144(256 KiB) may be sufficient. If WITH_SPNG=ON, it is not supported. + IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. + IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0. IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1. IMWRITE_EXR_TYPE = (3 << 4) + 0 /* 48 */, //!< override EXR storage type (FLOAT (FP32) is default) IMWRITE_EXR_COMPRESSION = (3 << 4) + 1 /* 49 */, //!< override EXR compression type (ZIP_COMPRESSION = 3 is default) @@ -105,22 +102,22 @@ enum ImwriteFlags { IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. IMWRITE_HDR_COMPRESSION = (5 << 4) + 0 /* 80 */, //!< specify HDR compression IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format - IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set. See ImwriteTiffResolutionUnitFlags. Default is IMWRITE_TIFF_RESOLUTION_UNIT_INCH. + IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI IMWRITE_TIFF_YDPI = 258,//!< For TIFF, use to specify the Y direction DPI IMWRITE_TIFF_COMPRESSION = 259,//!< For TIFF, use to specify the image compression scheme. See cv::ImwriteTiffCompressionFlags. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default. IMWRITE_TIFF_ROWSPERSTRIP = 278,//!< For TIFF, use to specify the number of rows per strip. - IMWRITE_TIFF_PREDICTOR = 317,//!< For TIFF, use to specify predictor. See cv::ImwriteTiffPredictorFlags. Default is IMWRITE_TIFF_PREDICTOR_HORIZONTAL . + IMWRITE_TIFF_PREDICTOR = 317,//!< For TIFF, use to specify predictor. See cv::ImwriteTiffPredictorFlags. IMWRITE_JPEG2000_COMPRESSION_X1000 = 272,//!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000. IMWRITE_AVIF_QUALITY = 512,//!< For AVIF, it can be a quality between 0 and 100 (the higher the better). Default is 95. IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_32F. Default is 8. - IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and 10(fastest). Default is 9. + IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and (fastest). Default is 9. IMWRITE_JPEGXL_QUALITY = 640,//!< For JPEG XL, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. If set, distance parameter is re-calicurated from quality level automatically. This parameter request libjxl v0.10 or later. IMWRITE_JPEGXL_EFFORT = 641,//!< For JPEG XL, encoder effort/speed level without affecting decoding speed; it is between 1 (fastest) and 10 (slowest). Default is 7. IMWRITE_JPEGXL_DISTANCE = 642,//!< For JPEG XL, distance level for lossy compression: target max butteraugli distance, lower = higher quality, 0 = lossless; range: 0 .. 25. Default is 1. IMWRITE_JPEGXL_DECODING_SPEED = 643,//!< For JPEG XL, decoding speed tier for the provided options; minimum is 0 (slowest to decode, best quality/density), and maximum is 4 (fastest to decode, at the cost of some quality/density). Default is 0. - IMWRITE_GIF_LOOP = 1024, //!< Not functional since 4.12.0. Replaced by cv::Animation::loop_count. - IMWRITE_GIF_SPEED = 1025, //!< Not functional since 4.12.0. Replaced by cv::Animation::durations. + IMWRITE_GIF_LOOP = 1024,//!< For GIF, it can be a loop flag from 0 to 65535. Default is 0 - loop forever. + IMWRITE_GIF_SPEED = 1025,//!< For GIF, it is between 1 (slowest) and 100 (fastest). Default is 96. IMWRITE_GIF_QUALITY = 1026, //!< For GIF, it can be a quality from 1 to 8. Default is 2. See cv::ImwriteGifCompressionFlags. IMWRITE_GIF_DITHER = 1027, //!< For GIF, it can be a quality from -1(most dither) to 3(no dither). Default is 0. IMWRITE_GIF_TRANSPARENCY = 1028, //!< For GIF, the alpha channel lower than this will be set to transparent. Default is 1. @@ -175,12 +172,7 @@ enum ImwriteTiffPredictorFlags { IMWRITE_TIFF_PREDICTOR_NONE = 1, //!< no prediction scheme used IMWRITE_TIFF_PREDICTOR_HORIZONTAL = 2, //!< horizontal differencing IMWRITE_TIFF_PREDICTOR_FLOATINGPOINT = 3 //!< floating point predictor -}; -enum ImwriteTiffResolutionUnitFlags { - IMWRITE_TIFF_RESOLUTION_UNIT_NONE = 1, //!< no absolute unit of measurement. - IMWRITE_TIFF_RESOLUTION_UNIT_INCH = 2, //!< inch - IMWRITE_TIFF_RESOLUTION_UNIT_CENTIMETER = 3, //!< centimeter }; enum ImwriteEXRTypeFlags { @@ -218,17 +210,6 @@ enum ImwritePNGFlags { IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. }; -//! Imwrite PNG specific values for IMWRITE_PNG_FILTER parameter key -enum ImwritePNGFilterFlags { - IMWRITE_PNG_FILTER_NONE = 8, //!< Applies no filter to the PNG image (useful when you want to save the raw pixel data without any compression filter). - IMWRITE_PNG_FILTER_SUB = 16, //!< Applies the "sub" filter, which calculates the difference between the current byte and the previous byte in the row. - IMWRITE_PNG_FILTER_UP = 32, //!< applies the "up" filter, which calculates the difference between the current byte and the corresponding byte directly above it. - IMWRITE_PNG_FILTER_AVG = 64, //!< applies the "average" filter, which calculates the average of the byte to the left and the byte above. - IMWRITE_PNG_FILTER_PAETH = 128, //!< applies the "Paeth" filter, a more complex filter that predicts the next pixel value based on neighboring pixels. - IMWRITE_PNG_FAST_FILTERS = (IMWRITE_PNG_FILTER_NONE | IMWRITE_PNG_FILTER_SUB | IMWRITE_PNG_FILTER_UP), //!< This is a combination of IMWRITE_PNG_FILTER_NONE, IMWRITE_PNG_FILTER_SUB, and IMWRITE_PNG_FILTER_UP, typically used for faster compression. - IMWRITE_PNG_ALL_FILTERS = (IMWRITE_PNG_FAST_FILTERS | IMWRITE_PNG_FILTER_AVG | IMWRITE_PNG_FILTER_PAETH) //!< This combines all available filters (NONE, SUB, UP, AVG, and PAETH), which will attempt to apply all of them for the best possible compression. - }; - //! Imwrite PAM specific tupletype flags used to define the 'TUPLETYPE' field of a PAM file. enum ImwritePAMFlags { IMWRITE_PAM_FORMAT_NULL = 0, @@ -257,17 +238,6 @@ enum ImwriteGIFCompressionFlags { IMWRITE_GIF_COLORTABLE_SIZE_256 = 8 }; -enum ImageMetadataType -{ - IMAGE_METADATA_UNKNOWN = -1, // Used when metadata type is unrecognized or not set - - IMAGE_METADATA_EXIF = 0, // EXIF metadata (e.g., camera info, GPS, orientation) - IMAGE_METADATA_XMP = 1, // XMP metadata (eXtensible Metadata Platform - Adobe format) - IMAGE_METADATA_ICCP = 2, // ICC Profile (color profile for color management) - - IMAGE_METADATA_MAX = 2 // Highest valid index (usually used for bounds checking) -}; - //! @} imgcodecs_flags /** @brief Represents an animation with multiple frames. @@ -277,25 +247,13 @@ It provides support for looping, background color settings, frame timing, and fr struct CV_EXPORTS_W_SIMPLE Animation { //! Number of times the animation should loop. 0 means infinite looping. - /*! @note At some file format, when N is set, whether it is displayed N or N+1 times depends on the implementation of the user application. This loop times behaviour has not been documented clearly. - * - (GIF) See https://issues.chromium.org/issues/40459899 - * And animated GIF with loop is extended with the Netscape Application Block(NAB), which it not a part of GIF89a specification. See https://en.wikipedia.org/wiki/GIF#Animated_GIF . - * - (WebP) See https://issues.chromium.org/issues/41276895 - */ CV_PROP_RW int loop_count; //! Background color of the animation in BGRA format. CV_PROP_RW Scalar bgcolor; //! Duration for each frame in milliseconds. - /*! @note (GIF) Due to file format limitation - * - Durations must be multiples of 10 milliseconds. Any provided value will be rounded down to the nearest 10ms (e.g., 88ms → 80ms). - * - 0ms(or smaller than expected in user application) duration may cause undefined behavior, e.g. it is handled with default duration. - * - Over 65535 * 10 milliseconds duration is not supported. - */ CV_PROP_RW std::vector durations; //! Vector of frames, where each Mat represents a single frame. CV_PROP_RW std::vector frames; - //! image that can be used for the format in addition to the animation or if animation is not supported in the reader (like in PNG). - CV_PROP_RW Mat still_image; /** @brief Constructs an Animation object with optional loop count and background color. @@ -305,11 +263,11 @@ struct CV_EXPORTS_W_SIMPLE Animation - If a negative value or a value beyond the maximum of `0xffff` (65535) is provided, it is reset to `0` (infinite looping) to maintain valid bounds. - @param bgColor A `Scalar` object representing the background color in BGR format: + @param bgColor A `Scalar` object representing the background color in BGRA format: - Defaults to `Scalar()`, indicating an empty color (usually transparent if supported). - This background color provides a solid fill behind frames that have transparency, ensuring a consistent display appearance. */ - CV_WRAP Animation(int loopCount = 0, Scalar bgColor = Scalar()); + Animation(int loopCount = 0, Scalar bgColor = Scalar()); }; /** @brief Loads an image from a file. @@ -362,7 +320,7 @@ Currently, the following file formats are supported: the environment variable `OPENCV_IO_MAX_IMAGE_PIXELS`. See @ref tutorial_env_reference. @param filename Name of the file to be loaded. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_COLOR_BGR. +@param flags Flag that can take values of `cv::ImreadModes`. */ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR_BGR ); @@ -371,29 +329,12 @@ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR_BGR ); This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts and the return value. @param filename Name of file to be loaded. @param dst object in which the image will be loaded. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_COLOR_BGR. +@param flags Flag that can take values of cv::ImreadModes @note The image passing through the img parameter can be pre-allocated. The memory is reused if the shape and the type match with the load image. */ CV_EXPORTS_W void imread( const String& filename, OutputArray dst, int flags = IMREAD_COLOR_BGR ); -/** @brief Reads an image from a file along with associated metadata. - -This function behaves similarly to cv::imread(), loading an image from the specified file. -In addition to the image pixel data, it also attempts to extract any available metadata -embedded in the file (such as EXIF, XMP, etc.), depending on file format support. - -@note In the case of color images, the decoded images will have the channels stored in **B G R** order. -@param filename Name of the file to be loaded. -@param metadataTypes Output vector with types of metadata chunks returned in metadata, see ImageMetadataType. -@param metadata Output vector of vectors or vector of matrices to store the retrieved metadata. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. - -@return The loaded image as a cv::Mat object. If the image cannot be read, the function returns an empty matrix. -*/ -CV_EXPORTS_W Mat imreadWithMetadata( const String& filename, CV_OUT std::vector& metadataTypes, - OutputArrayOfArrays metadata, int flags = IMREAD_ANYCOLOR); - /** @brief Loads a multi-page image from a file. The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects. @@ -434,19 +375,6 @@ The function imreadanimation loads frames from an animated image file (e.g., GIF */ CV_EXPORTS_W bool imreadanimation(const String& filename, CV_OUT Animation& animation, int start = 0, int count = INT16_MAX); -/** @brief Loads frames from an animated image buffer into an Animation structure. - -The function imdecodeanimation loads frames from an animated image buffer (e.g., GIF, AVIF, APNG, WEBP) into the provided Animation struct. - -@param buf A reference to an InputArray containing the image buffer. -@param animation A reference to an Animation structure where the loaded frames will be stored. It should be initialized before the function is called. -@param start The index of the first frame to load. This is optional and defaults to 0. -@param count The number of frames to load. This is optional and defaults to 32767. - -@return Returns true if the buffer was successfully loaded and frames were extracted; returns false otherwise. -*/ -CV_EXPORTS_W bool imdecodeanimation(InputArray buf, CV_OUT Animation& animation, int start = 0, int count = INT16_MAX); - /** @brief Saves an Animation to a specified file. The function imwriteanimation saves the provided Animation data to the specified file in an animated format. @@ -461,26 +389,6 @@ These parameters are used to specify additional options for the encoding process */ CV_EXPORTS_W bool imwriteanimation(const String& filename, const Animation& animation, const std::vector& params = std::vector()); -/** @brief Encodes an Animation to a memory buffer. - -The function imencodeanimation encodes the provided Animation data into a memory -buffer in an animated format. Supported formats depend on the implementation and -may include formats like GIF, AVIF, APNG, or WEBP. - -@param ext The file extension that determines the format of the encoded data. -@param animation A constant reference to an Animation struct containing the -frames and metadata to be encoded. -@param buf A reference to a vector of unsigned chars where the encoded data will -be stored. -@param params Optional format-specific parameters encoded as pairs (paramId_1, -paramValue_1, paramId_2, paramValue_2, ...). These parameters are used to -specify additional options for the encoding process. Refer to `cv::ImwriteFlags` -for details on possible parameters. - -@return Returns true if the animation was successfully encoded; returns false otherwise. -*/ -CV_EXPORTS_W bool imencodeanimation(const String& ext, const Animation& animation, CV_OUT std::vector& buf, const std::vector& params = std::vector()); - /** @brief Returns the number of images inside the given file The function imcount returns the number of pages in a multi-page image (e.g. TIFF), the number of frames in an animation (e.g. AVIF), and 1 otherwise. @@ -498,20 +406,20 @@ filename extension (see cv::imread for the list of extensions). In general, only single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function, with these exceptions: -- With OpenEXR encoder, only 32-bit float (CV_32F) images can be saved. More than 4 channels can be saved. (imread can load it then.) +- With OpenEXR encoder, only 32-bit float (CV_32F) images can be saved. - 8-bit unsigned (CV_8U) images are not supported. - With Radiance HDR encoder, non 64-bit float (CV_64F) images can be saved. - All images will be converted to 32-bit float (CV_32F). - With JPEG 2000 encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With JPEG XL encoder, 8-bit unsigned (CV_8U), 16-bit unsigned (CV_16U) and 32-bit float(CV_32F) images can be saved. - JPEG XL images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) / 32-bit float 4-channel (CV_32FC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255/65535/1.0. + To do this, create 8-bit (or 16-bit, 32-bit float) 4-channel image BGRA, where the alpha channel goes last. + Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535/1.0. - With PAM encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With PNG encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - - PNG images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255/65535(see the code sample below). + - PNG images with an alpha channel can be saved using this function. To do this, create + 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels + should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535 (see the code sample below). - With PGM/PPM encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With TIFF encoder, 8-bit unsigned (CV_8U), 8-bit signed (CV_8S), 16-bit unsigned (CV_16U), 16-bit signed (CV_16S), @@ -520,11 +428,6 @@ can be saved using this function, with these exceptions: - Multiple images (vector of Mat) can be saved in TIFF format (see the code sample below). - 32-bit float 3-channel (CV_32FC3) TIFF images will be saved using the LogLuv high dynamic range encoding (4 bytes per pixel) -- With GIF encoder, 8-bit unsigned (CV_8U) images can be saved. - - GIF images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255. - - 8-bit single-channel images (CV_8UC1) are not supported due to GIF's limitation to indexed color formats. If the image format is not supported, the image will be converted to 8-bit unsigned (CV_8U) and saved that way. @@ -542,20 +445,6 @@ It also demonstrates how to save multiple images in a TIFF file: CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector()); -/** @brief Saves an image to a specified file with metadata - -The function imwriteWithMetadata saves the image to the specified file. It does the same thing as imwrite, but additionally writes metadata if the corresponding format supports it. -@param filename Name of the file. As with imwrite, image format is determined by the file extension. -@param img (Mat or vector of Mat) Image or Images to be saved. -@param metadataTypes Vector with types of metadata chucks stored in metadata to write, see ImageMetadataType. -@param metadata Vector of vectors or vector of matrices with chunks of metadata to store into the file -@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags -*/ -CV_EXPORTS_W bool imwriteWithMetadata( const String& filename, InputArray img, - const std::vector& metadataTypes, - InputArrayOfArrays& metadata, - const std::vector& params = std::vector()); - //! @brief multi-image overload for bindings CV_WRAP static inline bool imwritemulti(const String& filename, InputArrayOfArrays img, @@ -573,31 +462,13 @@ See cv::imread for the list of supported formats and flags description. @note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. */ CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); -/** @brief Reads an image from a memory buffer and extracts associated metadata. - -This function decodes an image from the specified memory buffer. If the buffer is too short or -contains invalid data, the function returns an empty matrix ( Mat::data==NULL ). - -See cv::imread for the list of supported formats and flags description. - -@note In the case of color images, the decoded images will have the channels stored in **B G R** order. -@param buf Input array or vector of bytes containing the encoded image data. -@param metadataTypes Output vector with types of metadata chucks returned in metadata, see cv::ImageMetadataType -@param metadata Output vector of vectors or vector of matrices to store the retrieved metadata -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. - -@return The decoded image as a cv::Mat object. If decoding fails, the function returns an empty matrix. -*/ -CV_EXPORTS_W Mat imdecodeWithMetadata( InputArray buf, CV_OUT std::vector& metadataTypes, - OutputArrayOfArrays metadata, int flags = IMREAD_ANYCOLOR ); - /** @overload @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. +@param flags The same flags as in cv::imread, see cv::ImreadModes. @param dst The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. In case of decoder failure the function returns empty cv::Mat object, but does not release user-provided dst buffer. @@ -613,7 +484,7 @@ See cv::imreadmulti for the list of supported formats and flags description. @note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. @param mats A vector of Mat objects holding each page, if more than one. @param range A continuous selection of pages. */ @@ -633,24 +504,6 @@ CV_EXPORTS_W bool imencode( const String& ext, InputArray img, CV_OUT std::vector& buf, const std::vector& params = std::vector()); -/** @brief Encodes an image into a memory buffer. - -The function imencode compresses the image and stores it in the memory buffer that is resized to fit the -result. See cv::imwrite for the list of supported formats and flags description. - -@param ext File extension that defines the output format. Must include a leading period. -@param img Image to be compressed. -@param metadataTypes Vector with types of metadata chucks stored in metadata to write, see ImageMetadataType. -@param metadata Vector of vectors or vector of matrices with chunks of metadata to store into the file -@param buf Output buffer resized to fit the compressed image. -@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags. -*/ -CV_EXPORTS_W bool imencodeWithMetadata( const String& ext, InputArray img, - const std::vector& metadataTypes, - InputArrayOfArrays metadata, - CV_OUT std::vector& buf, - const std::vector& params = std::vector()); - /** @brief Encodes array of images into a memory buffer. The function is analog to cv::imencode for in-memory multi-page image compression. @@ -674,7 +527,7 @@ This can be useful for verifying support for a given image format before attempt @return true if an image reader for the specified file is available and the file can be opened, false otherwise. @note The function checks the availability of image codecs that are either built into OpenCV or dynamically loaded. -It does not load the image codec implementation and decode data, but uses signature check. +It does not check for the actual existence of the file but rather the ability to read the specified file type. If the file cannot be opened or the format is unsupported, the function will return false. @sa cv::haveImageWriter, cv::imread, cv::imdecode diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc.hpp index 1bcf0c8b19ed9bfe72593080b4bbd5264c74348f..eb968b9e40deb716f6a65769b3ff730c786e6840 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc.hpp @@ -44,6 +44,12 @@ #define OPENCV_IMGPROC_HPP #include "opencv2/core.hpp" +#include "opencv2/imgproc/cust_ncc.h" +#include "opencv2/imgproc/cust_threshold_s16.h" +#include "opencv2/imgproc/cust_threshold_u16.h" +#include "opencv2/imgproc/cust_filter_and_csc.h" +#include "opencv2/imgproc/cust_mag_and_ang.h" + /** @defgroup imgproc Image Processing @@ -118,7 +124,7 @@ This module offers a comprehensive suite of image processing functions, enabling coordinates needs to be retrieved. In the simplest case, the coordinates can be just rounded to the nearest integer coordinates and the corresponding pixel can be used. This is called a nearest-neighbor interpolation. However, a better result can be achieved by using more - sophisticated [interpolation methods](https://en.wikipedia.org/wiki/Multivariate_interpolation) , + sophisticated [interpolation methods](http://en.wikipedia.org/wiki/Multivariate_interpolation) , where a polynomial function is fit into some neighborhood of the computed pixel \f$(f_x(x,y), f_y(x,y))\f$, and then the value of the polynomial at \f$(f_x(x,y), f_y(x,y))\f$ is taken as the interpolated pixel value. In OpenCV, you can choose between several interpolation methods. See @@ -235,9 +241,8 @@ enum MorphShapes { MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] MORPH_CROSS = 1, //!< a cross-shaped structuring element: //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f] - MORPH_ELLIPSE = 2, //!< an elliptic structuring element, that is, a filled ellipse inscribed + MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed //!< into the rectangle Rect(0, 0, esize.width, esize.height) - MORPH_DIAMOND = 3 //!< a diamond structuring element defined by Manhattan distance }; //! @} imgproc_filter @@ -330,8 +335,7 @@ enum ThresholdTypes { THRESH_TOZERO_INV = 4, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f] THRESH_MASK = 7, THRESH_OTSU = 8, //!< flag, use Otsu algorithm to choose the optimal threshold value - THRESH_TRIANGLE = 16, //!< flag, use Triangle algorithm to choose the optimal threshold value - THRESH_DRYRUN = 128 //!< flag, compute threshold only (useful for OTSU/TRIANGLE) but does not actually run thresholding + THRESH_TRIANGLE = 16 //!< flag, use Triangle algorithm to choose the optimal threshold value }; //! adaptive threshold algorithm @@ -1112,27 +1116,13 @@ public: */ CV_WRAP Subdiv2D(Rect rect); - /** @overload */ - CV_WRAP Subdiv2D(Rect2f rect2f); - - /** @overload - - @brief Creates a new empty Delaunay subdivision + /** @brief Creates a new empty Delaunay subdivision @param rect Rectangle that includes all of the 2D points that are to be added to the subdivision. */ CV_WRAP void initDelaunay(Rect rect); - /** @overload - - @brief Creates a new empty Delaunay subdivision - - @param rect Rectangle that includes all of the 2d points that are to be added to the subdivision. - - */ - CV_WRAP_AS(initDelaunay2f) CV_WRAP void initDelaunay(Rect2f rect); - /** @brief Insert a single point into a Delaunay triangulation. @param pt Point to insert. @@ -1482,7 +1472,7 @@ CV_EXPORTS_W void getDerivKernels( OutputArray kx, OutputArray ky, /** @brief Returns Gabor filter coefficients. For more details about gabor filter equations and parameters, see: [Gabor -Filter](https://en.wikipedia.org/wiki/Gabor_filter). +Filter](http://en.wikipedia.org/wiki/Gabor_filter). @param ksize Size of the filter returned. @param sigma Standard deviation of the gaussian envelope. @@ -1564,7 +1554,7 @@ CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, /** @brief Applies the bilateral filter to an image. The function applies bilateral filtering to the input image, as described in -https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html +http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is very slow compared to most filters. @@ -1674,7 +1664,7 @@ stackBlur can generate similar results as Gaussian blur, and the time consumptio It creates a kind of moving stack of colors whilst scanning through the image. Thereby it just has to add one new block of color to the right side of the stack and remove the leftmost color. The remaining colors on the topmost layer of the stack are either added on or reduced by one, depending on if they are on the right or on the left side of the stack. The only supported borderType is BORDER_REPLICATE. -Original paper was proposed by Mario Klingemann, which can be found https://underdestruction.com/2004/02/25/stackblur-2004. +Original paper was proposed by Mario Klingemann, which can be found http://underdestruction.com/2004/02/25/stackblur-2004. @param src input image. The number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S or CV_32F. @@ -1889,7 +1879,7 @@ Check @ref tutorial_canny_detector "the corresponding tutorial" for more details The function finds edges in the input image and marks them in the output map edges using the Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The largest value is used to find initial segments of strong edges. See - + @param image 8-bit input image. @param edges output edge map; single channels 8-bit image, which has the same size as image . @@ -2158,7 +2148,7 @@ An example using the Hough line detector /** @brief Finds lines in a binary image using the standard Hough transform. The function implements the standard or standard multi-scale Hough transform algorithm for line -detection. See for a good explanation of Hough +detection. See for a good explanation of Hough transform. @param image 8-bit, single-channel binary source image. The image may be modified by the function. @@ -3001,15 +2991,15 @@ CV_EXPORTS_W void accumulateWeighted( InputArray src, InputOutputArray dst, The operation takes advantage of the Fourier shift theorem for detecting the translational shift in the frequency domain. It can be used for fast image registration as well as motion estimation. For -more information please see +more information please see Calculates the cross-power spectrum of two supplied source arrays. The arrays are padded if needed with getOptimalDFTSize. The function performs the following equations: -- First it applies a Hanning window to each image to remove possible edge effects, if it's provided -by user. See @ref createHanningWindow and . This window may -be cached until the array size changes to speed up processing time. +- First it applies a Hanning window (see ) to each +image to remove possible edge effects. This window is cached until the array size changes to speed +up processing time. - Next it computes the forward DFTs of each source array: \f[\mathbf{G}_a = \mathcal{F}\{src_1\}, \; \mathbf{G}_b = \mathcal{F}\{src_2\}\f] where \f$\mathcal{F}\f$ is the forward DFT. @@ -3037,7 +3027,7 @@ CV_EXPORTS_W Point2d phaseCorrelate(InputArray src1, InputArray src2, /** @brief This function computes a Hanning window coefficients in two dimensions. -See (https://en.wikipedia.org/wiki/Hann_function) and (https://en.wikipedia.org/wiki/Window_function) +See (http://en.wikipedia.org/wiki/Hann_function) and (http://en.wikipedia.org/wiki/Window_function) for more information. An example is shown below: @@ -3085,10 +3075,9 @@ Also, the special values #THRESH_OTSU or #THRESH_TRIANGLE may be combined with o above values. In these cases, the function determines the optimal threshold value using the Otsu's or Triangle algorithm and uses it instead of the specified thresh. -@note Currently, the Otsu's method is implemented only for CV_8UC1 and CV_16UC1 images, -and the Triangle's method is implemented only for CV_8UC1 images. +@note Currently, the Otsu's and Triangle methods are implemented only for 8-bit single-channel images. -@param src input array (multiple-channel, CV_8U, CV_16S, CV_16U, CV_32F or CV_64F). +@param src input array (multiple-channel, 8-bit or 32-bit floating point). @param dst output array of the same size and type and the same number of channels as src. @param thresh threshold value. @param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding @@ -3096,30 +3085,11 @@ types. @param type thresholding type (see #ThresholdTypes). @return the computed threshold value if Otsu's or Triangle methods used. -@sa thresholdWithMask, adaptiveThreshold, findContours, compare, min, max +@sa adaptiveThreshold, findContours, compare, min, max */ CV_EXPORTS_W double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type ); -/** @brief Same as #threshold, but with an optional mask - -@note If the mask is empty, #thresholdWithMask is equivalent to #threshold. -If the mask is not empty, dst *must* be of the same size and type as src, so that -outliers pixels are left as-is - -@param src input array (multiple-channel, 8-bit or 32-bit floating point). -@param dst output array of the same size and type and the same number of channels as src. -@param mask optional mask (same size as src, 8-bit). -@param thresh threshold value. -@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding -types. -@param type thresholding type (see #ThresholdTypes). -@return the computed threshold value if Otsu's or Triangle methods used. - -@sa threshold, adaptiveThreshold, findContours, compare, min, max -*/ -CV_EXPORTS_W double thresholdWithMask( InputArray src, InputOutputArray dst, InputArray mask, - double thresh, double maxval, int type ); /** @brief Applies an adaptive threshold to an array. @@ -3522,7 +3492,7 @@ An example using the GrabCut algorithm /** @brief Runs the GrabCut algorithm. -The function implements the [GrabCut image segmentation algorithm](https://en.wikipedia.org/wiki/GrabCut). +The function implements the [GrabCut image segmentation algorithm](http://en.wikipedia.org/wiki/GrabCut). @param img Input 8-bit 3-channel image. @param mask Input/output 8-bit single-channel mask. The mask is initialized by the function when @@ -3849,7 +3819,7 @@ CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); /** @brief Calculates seven Hu invariants. The function calculates seven Hu invariants (introduced in @cite Hu62; see also -) defined as: +) defined as: \f[\begin{array}{l} hu[0]= \eta _{20}+ \eta _{02} \\ hu[1]=( \eta _{20}- \eta _{02})^{2}+4 \eta _{11}^{2} \\ hu[2]=( \eta _{30}-3 \eta _{12})^{2}+ (3 \eta _{21}- \eta _{03})^{2} \\ hu[3]=( \eta _{30}+ \eta _{12})^{2}+ ( \eta _{21}+ \eta _{03})^{2} \\ hu[4]=( \eta _{30}-3 \eta _{12})( \eta _{30}+ \eta _{12})[( \eta _{30}+ \eta _{12})^{2}-3( \eta _{21}+ \eta _{03})^{2}]+(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ hu[5]=( \eta _{20}- \eta _{02})[( \eta _{30}+ \eta _{12})^{2}- ( \eta _{21}+ \eta _{03})^{2}]+4 \eta _{11}( \eta _{30}+ \eta _{12})( \eta _{21}+ \eta _{03}) \\ hu[6]=(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}]-( \eta _{30}-3 \eta _{12})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ \end{array}\f] @@ -3945,7 +3915,7 @@ is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \t of channels as template or only one channel, which is then used for all template and image channels. If the data type is #CV_8U, the mask is interpreted as a binary mask, meaning only elements where mask is nonzero are used and are kept unchanged independent - of the actual mask value (weight equals 1). For data type #CV_32F, the mask values are + of the actual mask value (weight equals 1). For data tpye #CV_32F, the mask values are used as weights. The exact formulas are documented in #TemplateMatchModes. */ CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, @@ -4087,7 +4057,7 @@ CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays con The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less vertices so that the distance between them is less or equal to the specified precision. It uses the -Douglas-Peucker algorithm +Douglas-Peucker algorithm @param curve Input vector of a 2D point stored in std::vector or Mat @param approxCurve Result of the approximation. The type should match the type of the input curve. @@ -4175,11 +4145,7 @@ CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false ); /** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set. The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a -specified point set. The angle of rotation represents the angle between the line connecting the starting -and ending points (based on the clockwise order with greatest index for the corner with greatest \f$y\f$) -and the horizontal axis. This angle always falls between \f$[-90, 0)\f$ because, if the object -rotates more than a rect angle, the next edge is used to measure the angle. The starting and ending points change -as the object rotates.Developer should keep in mind that the returned RotatedRect can contain negative +specified point set. Developer should keep in mind that the returned RotatedRect can contain negative indices when data is close to the containing Mat element boundary. @param points Input vector of 2D points, stored in std::vector\<\> or Mat @@ -4188,9 +4154,7 @@ CV_EXPORTS_W RotatedRect minAreaRect( InputArray points ); /** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle. -The function finds the four vertices of a rotated rectangle. The four vertices are returned -in clockwise order starting from the point with greatest \f$y\f$. If two points have the -same \f$y\f$ coordinate the rightmost is the starting point. This function is useful to draw the +The function finds the four vertices of a rotated rectangle. This function is useful to draw the rectangle. In C++, instead of using this function, you can directly use RotatedRect::points method. Please visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses for contours" for more information. @@ -4341,9 +4305,6 @@ ellipse/rotatedRect data contains negative indices, due to the data points being border of the containing Mat element. @param points Input 2D point set, stored in std::vector\<\> or Mat - -@note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. -@note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipse( InputArray points ); @@ -4381,9 +4342,6 @@ CV_EXPORTS_W RotatedRect fitEllipse( InputArray points ); \f} @param points Input 2D point set, stored in std::vector\<\> or Mat - - @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. - @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points ); @@ -4429,26 +4387,9 @@ CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points ); The scaling factor guarantees that \f$A^T C A =1\f$. @param points Input 2D point set, stored in std::vector\<\> or Mat - - @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. - @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipseDirect( InputArray points ); -/** @brief Compute for each 2d point the nearest 2d point located on a given ellipse. - - The function computes the nearest 2d location on a given ellipse for a vector of 2d points and is based on @cite Chatfield2017 code. - This function can be used to compute for instance the ellipse fitting error. - - @param ellipse_params Ellipse parameters - @param points Input 2d points - @param closest_pts For each 2d point, their corresponding closest 2d point located on a given ellipse - - @note Input point types are @ref Point2i or @ref Point2f - @see fitEllipse, fitEllipseAMS, fitEllipseDirect - */ -CV_EXPORTS_W void getClosestEllipsePoints( const RotatedRect& ellipse_params, InputArray points, OutputArray closest_pts ); - /** @brief Fits a line to a 2D or 3D point set. The function fitLine fits a line to a 2D or 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where @@ -4467,7 +4408,7 @@ of the following: - DIST_HUBER \f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] -The algorithm is based on the M-estimator ( ) technique +The algorithm is based on the M-estimator ( ) technique that iteratively fits the line using the weighted least-squares algorithm. After each iteration the weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . @@ -4915,11 +4856,6 @@ The function cv::putText renders the specified text string in the image. Symbols using the specified font are replaced by question marks. See #getTextSize for a text rendering code example. -The `fontScale` parameter is a scale factor that is multiplied by the base font size: -- When scale > 1, the text is magnified. -- When 0 < scale < 1, the text is minimized. -- When scale < 0, the text is mirrored or reversed. - @param img Image. @param text Text string to be drawn. @param org Bottom-left corner of the text string in the image. diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/bindings.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/bindings.hpp index ad507a5bf9d48f1d9dc22d770bcb7d131e7640fd..c69527a779452455f31dc0ce20cfe53587f4419e 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/bindings.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/bindings.hpp @@ -21,34 +21,14 @@ void HoughLinesWithAccumulator( InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, - double min_theta = 0, double max_theta = CV_PI, - bool use_edgeval = false + double min_theta = 0, double max_theta = CV_PI ) { std::vector lines_acc; - HoughLines(image, lines_acc, rho, theta, threshold, srn, stn, min_theta, max_theta, use_edgeval); + HoughLines(image, lines_acc, rho, theta, threshold, srn, stn, min_theta, max_theta); Mat(lines_acc).copyTo(lines); } -/** @brief Finds circles in a grayscale image using the Hough transform and get accumulator. - * - * @note This function is for bindings use only. Use original function in C++ code - * - * @sa HoughCircles - */ -CV_WRAP static inline -void HoughCirclesWithAccumulator( - InputArray image, OutputArray circles, - int method, double dp, double minDist, - double param1 = 100, double param2 = 100, - int minRadius = 0, int maxRadius = 0 -) -{ - std::vector circles_acc; - HoughCircles(image, circles_acc, method, dp, minDist, param1, param2, minRadius, maxRadius); - Mat(1, static_cast(circles_acc.size()), CV_32FC4, &circles_acc.front()).copyTo(circles); -} - } // namespace #endif // OPENCV_IMGPROC_BINDINGS_HPP diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h new file mode 100644 index 0000000000000000000000000000000000000000..8670e6d975f89ee187c7a6ac4a25af2e857d9233 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h @@ -0,0 +1,30 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_FILTER_AND_CSC_H +#define OPENCV_CUST_FILTER_AND_CSC_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { +CV_EXPORTS void filter_and_csc(InputArray &src, OutputArray &dst); + +} +#endif // OPENCV_CUST_FILTER_AND_CSC_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h new file mode 100644 index 0000000000000000000000000000000000000000..75bc790774ca8d6f4dfa101393078105e8e7520b --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h @@ -0,0 +1,30 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_MAG_AND_ANG_H +#define OPENCV_CUST_MAG_AND_ANG_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { +CV_EXPORTS void mag_and_ang(InputArray src,OutputArray dst_mag,OutputArray dst_ang); + +} +#endif // OPENCV_CUST_MAG_AND_ANG_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_ncc.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_ncc.h new file mode 100644 index 0000000000000000000000000000000000000000..d27f3e0b2ba9c95126062676272bed1c60d7e30e --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_ncc.h @@ -0,0 +1,31 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_NCC_H +#define OPENCV_CUST_NCC_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void ncc(cv::Mat& src1_input,cv::Mat& src2_input,// + double& number,double& sum1,double& sum2); +} + +#endif // OPENCV_CUST_NCC_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_s16.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_s16.h new file mode 100644 index 0000000000000000000000000000000000000000..5e60ac4206d5ab999c2b30ece67f6084dd6e5048 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_s16.h @@ -0,0 +1,31 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_THRESHOLD_S16_H +#define OPENCV_CUST_THRESHOLD_S16_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void threshold_s16(cv::Mat& input, cv::Mat& output, + double MIN_VAL, double MAX_VAL); +} + +#endif // OPENCV_CUST_THRESHOLD_S16_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_u16.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_u16.h new file mode 100644 index 0000000000000000000000000000000000000000..95ad873d1c7531285875109fcd9566ba82ec9b39 --- /dev/null +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/cust_threshold_u16.h @@ -0,0 +1,31 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) +*/ + +#ifndef OPENCV_CUST_THRESHOLD_U16_H +#define OPENCV_CUST_THRESHOLD_U16_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void threshold_u16(cv::Mat& input, cv::Mat& output, + double MIN_VAL, double MAX_VAL); +} + +#endif // OPENCV_CUST_THRESHOLD_U16_H \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/types_c.h b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/types_c.h index 14a0ec796bbe81b53d012be81efd91a20b8eaecf..255ed0c37f65a73de494e06e4c65c216e6593486 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/types_c.h +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/imgproc/types_c.h @@ -389,7 +389,6 @@ enum MorphShapes_c CV_SHAPE_RECT =0, CV_SHAPE_CROSS =1, CV_SHAPE_ELLIPSE =2, - CV_SHAPE_DIAMOND =3, CV_SHAPE_CUSTOM =100 //!< custom structuring element }; @@ -611,11 +610,9 @@ enum CV_THRESH_MASK =7, CV_THRESH_OTSU =8, /**< use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */ - CV_THRESH_TRIANGLE =16, /**< use Triangle algorithm to choose the optimal threshold value; + CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values, but not with CV_THRESH_OTSU */ - CV_THRESH_DRYRUN =128 /**< compute threshold only (useful for OTSU/TRIANGLE) but does not - actually run thresholding */ }; /** Adaptive threshold methods */ diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/ml.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/ml.hpp index b66a300402863d308ff1508235302359b5a6e285..d537ab7759b6888994fe7793b652ee310c675b51 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/ml.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/ml.hpp @@ -256,7 +256,7 @@ public: @param filename The input file name @param headerLineCount The number of lines in the beginning to skip; besides the header, the - function also skips empty lines and lines starting with `#` + function also skips empty lines and lines staring with `#` @param responseStartIdx Index of the first output variable. If -1, the function considers the last variable as the response @param responseEndIdx Index of the last output variable + 1. If -1, then there is single diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect.hpp index 4a8544b9104fc75917f2ff17f28b127db0d0b1df..7f1189060806121c049ff6453a698a77cd29e2df 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect.hpp @@ -729,8 +729,7 @@ public: }; enum ECIEncodings { - ECI_SHIFT_JIS = 20, - ECI_UTF8 = 26, + ECI_UTF8 = 26 }; /** @brief QR code encoder parameters. */ @@ -742,10 +741,10 @@ public: CV_PROP_RW int version; //! The optional level of error correction (by default - the lowest). - CV_PROP_RW QRCodeEncoder::CorrectionLevel correction_level; + CV_PROP_RW CorrectionLevel correction_level; //! The optional encoding mode - Numeric, Alphanumeric, Byte, Kanji, ECI or Structured Append. - CV_PROP_RW QRCodeEncoder::EncodeMode mode; + CV_PROP_RW EncodeMode mode; //! The optional number of QR codes to generate in Structured Append mode. CV_PROP_RW int structure_number; @@ -809,13 +808,6 @@ public: */ CV_WRAP std::string detectAndDecodeCurved(InputArray img, OutputArray points=noArray(), OutputArray straight_qrcode = noArray()); - - /** @brief Returns a kind of encoding for the decoded info from the latest @ref decode or @ref detectAndDecode call - @param codeIdx an index of the previously decoded QR code. - When @ref decode or @ref detectAndDecode is used, valid value is zero. - For @ref decodeMulti or @ref detectAndDecodeMulti use indices corresponding to the output order. - */ - CV_WRAP QRCodeEncoder::ECIEncodings getEncoding(int codeIdx = 0); }; class CV_EXPORTS_W_SIMPLE QRCodeDetectorAruco : public GraphicalCodeDetector { diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/aruco_detector.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/aruco_detector.hpp index c081989645a346d7dc0f94fb658c3ef2efda34de..9d30d55d176e44eae05d26e3e66053284451b8c2 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/aruco_detector.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/aruco_detector.hpp @@ -285,16 +285,6 @@ public: const DetectorParameters &detectorParams = DetectorParameters(), const RefineParameters& refineParams = RefineParameters()); - /** @brief ArucoDetector constructor for multiple dictionaries - * - * @param dictionaries indicates the type of markers that will be searched. Empty dictionaries will throw an error. - * @param detectorParams marker detection parameters - * @param refineParams marker refine detection parameters - */ - CV_WRAP ArucoDetector(const std::vector &dictionaries, - const DetectorParameters &detectorParams = DetectorParameters(), - const RefineParameters& refineParams = RefineParameters()); - /** @brief Basic marker detection * * @param image input image @@ -307,7 +297,7 @@ public: * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a * correct codification. Useful for debugging purposes. * - * Performs marker detection in the input image. Only markers included in the first specified dictionary + * Performs marker detection in the input image. Only markers included in the specific dictionary * are searched. For each detected marker, it returns the 2D position of its corner in the image * and its corresponding identifier. * Note that this function does not perform pose estimation. @@ -339,8 +329,6 @@ public: * If camera parameters and distortion coefficients are provided, missing markers are reprojected * using projectPoint function. If not, missing marker projections are interpolated using global * homography, and all the marker corners in the board must have the same Z coordinate. - * @note This function assumes that the board only contains markers from one dictionary, so only the - * first configured dictionary is used. It has to match the dictionary of the board to work properly. */ CV_WRAP void refineDetectedMarkers(InputArray image, const Board &board, InputOutputArrayOfArrays detectedCorners, @@ -348,59 +336,9 @@ public: InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(), OutputArray recoveredIdxs = noArray()) const; - /** @brief Basic marker detection - * - * @param image input image - * @param corners vector of detected marker corners. For each marker, its four corners - * are provided, (e.g std::vector > ). For N detected markers, - * the dimensions of this array is Nx4. The order of the corners is clockwise. - * @param ids vector of identifiers of the detected markers. The identifier is of type int - * (e.g. std::vector). For N detected markers, the size of ids is also N. - * The identifiers have the same order than the markers in the imgPoints array. - * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a - * correct codification. Useful for debugging purposes. - * @param dictIndices vector of dictionary indices for each detected marker. Use getDictionaries() to get the - * list of corresponding dictionaries. - * - * Performs marker detection in the input image. Only markers included in the specific dictionaries - * are searched. For each detected marker, it returns the 2D position of its corner in the image - * and its corresponding identifier. - * Note that this function does not perform pose estimation. - * @note The function does not correct lens distortion or takes it into account. It's recommended to undistort - * input image with corresponding camera model, if camera parameters are known - * @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard - */ - CV_WRAP void detectMarkersMultiDict(InputArray image, OutputArrayOfArrays corners, OutputArray ids, - OutputArrayOfArrays rejectedImgPoints = noArray(), OutputArray dictIndices = noArray()) const; - - /** @brief Returns first dictionary from internal list used for marker detection. - * - * @return The first dictionary from the configured ArucoDetector. - */ CV_WRAP const Dictionary& getDictionary() const; - - /** @brief Sets and replaces the first dictionary in internal list to be used for marker detection. - * - * @param dictionary The new dictionary that will replace the first dictionary in the internal list. - */ CV_WRAP void setDictionary(const Dictionary& dictionary); - /** @brief Returns all dictionaries currently used for marker detection as a vector. - * - * @return A std::vector containing all dictionaries used by the ArucoDetector. - */ - CV_WRAP std::vector getDictionaries() const; - - /** @brief Sets the entire collection of dictionaries to be used for marker detection, replacing any existing dictionaries. - * - * @param dictionaries A std::vector containing the new set of dictionaries to be used. - * - * Configures the ArucoDetector to use the provided vector of dictionaries for marker detection. - * This method replaces any dictionaries that were previously set. - * @note Setting an empty vector of dictionaries will throw an error. - */ - CV_WRAP void setDictionaries(const std::vector& dictionaries); - CV_WRAP const DetectorParameters& getDetectorParameters() const; CV_WRAP void setDetectorParameters(const DetectorParameters& detectorParameters); diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/charuco_detector.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/charuco_detector.hpp index e9681521d3cf192b15018e04b98ce7c12265f4d1..e10cb3f0254220f51208d76a4bdc5ee251a0504f 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/charuco_detector.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/charuco_detector.hpp @@ -16,7 +16,6 @@ struct CV_EXPORTS_W_SIMPLE CharucoParameters { CV_WRAP CharucoParameters() { minMarkers = 2; tryRefineMarkers = false; - checkMarkers = true; } /// cameraMatrix optional 3x3 floating-point camera matrix CV_PROP_RW Mat cameraMatrix; @@ -29,9 +28,6 @@ struct CV_EXPORTS_W_SIMPLE CharucoParameters { /// try to use refine board, default false CV_PROP_RW bool tryRefineMarkers; - - /// run check to verify that markers belong to the same board, default true - CV_PROP_RW bool checkMarkers; }; class CV_EXPORTS_W CharucoDetector : public Algorithm { diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp index adc52379b9030978fd4118967a45b94e7ead46e7..ed697c50c0556b615d0e078ba1ee3cb0803078e5 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp @@ -73,17 +73,6 @@ public: */ CV_WRAP bool detectAndDecodeMulti(InputArray img, CV_OUT std::vector& decoded_info, OutputArray points = noArray(), OutputArrayOfArrays straight_code = noArray()) const; - -#ifdef OPENCV_BINDINGS_PARSER - CV_WRAP_AS(detectAndDecodeBytes) NativeByteArray detectAndDecode(InputArray img, OutputArray points = noArray(), - OutputArray straight_code = noArray()) const; - CV_WRAP_AS(decodeBytes) NativeByteArray decode(InputArray img, InputArray points, OutputArray straight_code = noArray()) const; - CV_WRAP_AS(decodeBytesMulti) bool decodeMulti(InputArray img, InputArray points, CV_OUT std::vector& decoded_info, - OutputArrayOfArrays straight_code = noArray()) const; - CV_WRAP_AS(detectAndDecodeBytesMulti) bool detectAndDecodeMulti(InputArray img, CV_OUT std::vector& decoded_info, OutputArray points = noArray(), - OutputArrayOfArrays straight_code = noArray()) const; -#endif - struct Impl; protected: Ptr p; diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/opencv_modules.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/opencv_modules.hpp index 99ed98c86fe3bba3d7b8c740ec45a48ced25231c..6e93caa02020c38b07a390e38f63f20d8a68bbad 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/opencv_modules.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/opencv_modules.hpp @@ -15,6 +15,7 @@ #define HAVE_OPENCV_DNN #define HAVE_OPENCV_FEATURES2D #define HAVE_OPENCV_FLANN +#define HAVE_OPENCV_GAPI #define HAVE_OPENCV_HIGHGUI #define HAVE_OPENCV_IMGCODECS #define HAVE_OPENCV_IMGPROC diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/stitching/detail/seam_finders.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/stitching/detail/seam_finders.hpp index bae7aa0135063ac18daefaf3a026feca4950f869..9ccfd144247111947b41e5040c4ad13e0ce3ff08 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/stitching/detail/seam_finders.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/stitching/detail/seam_finders.hpp @@ -235,7 +235,7 @@ public: enum CostType { COST_COLOR, COST_COLOR_GRAD }; }; -/** @brief Minimum graph cut-based seam estimator. See details in @cite Kwatra03 . +/** @brief Minimum graph cut-based seam estimator. See details in @cite V03 . */ class CV_EXPORTS_W GraphCutSeamFinder : public GraphCutSeamFinderBase, public SeamFinder { diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/video/tracking.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/video/tracking.hpp index 86749f72b0ef9b3b58011c1554da3dc5da91a52d..ac3788772a3680c003c020c01bc323bb26bacc7a 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/video/tracking.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/video/tracking.hpp @@ -46,9 +46,6 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" -#ifdef HAVE_OPENCV_DNN -# include "opencv2/dnn.hpp" -#endif namespace cv { @@ -829,13 +826,6 @@ public: static CV_WRAP Ptr create(const TrackerGOTURN::Params& parameters = TrackerGOTURN::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - @param model pre-loaded GOTURN model - */ - static CV_WRAP Ptr create(const dnn::Net& model); -#endif - //void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE; //bool update(InputArray image, CV_OUT Rect& boundingBox) CV_OVERRIDE; }; @@ -863,16 +853,6 @@ public: static CV_WRAP Ptr create(const TrackerDaSiamRPN::Params& parameters = TrackerDaSiamRPN::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param siam_rpn pre-loaded SiamRPN model - * @param kernel_cls1 pre-loaded CLS model - * @param kernel_r1 pre-loaded R1 model - */ - static CV_WRAP - Ptr create(const dnn::Net& siam_rpn, const dnn::Net& kernel_cls1, const dnn::Net& kernel_r1); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; @@ -911,15 +891,6 @@ public: static CV_WRAP Ptr create(const TrackerNano::Params& parameters = TrackerNano::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param backbone pre-loaded backbone model - * @param neckhead pre-loaded neckhead model - */ - static CV_WRAP - Ptr create(const dnn::Net& backbone, const dnn::Net& neckhead); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; @@ -958,18 +929,6 @@ public: static CV_WRAP Ptr create(const TrackerVit::Params& parameters = TrackerVit::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param model pre-loaded DNN model - * @param meanvalue mean value for image preprocessing - * @param stdvalue std value for image preprocessing - * @param tracking_score_threshold threshold for tracking score - */ - static CV_WRAP - Ptr create(const dnn::Net& model, Scalar meanvalue = Scalar(0.485, 0.456, 0.406), - Scalar stdvalue = Scalar(0.229, 0.224, 0.225), float tracking_score_threshold = 0.20f); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; diff --git a/vendor/opensource/opencv/clang/include/opencv4/opencv2/videoio.hpp b/vendor/opensource/opencv/clang/include/opencv4/opencv2/videoio.hpp index 2457703f78bb48581dfa2d6703e9ee73277bed66..6e50f87e44c13067bd002df995302d20d86fd941 100644 --- a/vendor/opensource/opencv/clang/include/opencv4/opencv2/videoio.hpp +++ b/vendor/opensource/opencv/clang/include/opencv4/opencv2/videoio.hpp @@ -128,7 +128,7 @@ enum VideoCaptureAPIs { CAP_INTEL_MFX = 2300, //!< Intel MediaSDK CAP_XINE = 2400, //!< XINE engine (Linux) CAP_UEYE = 2500, //!< uEye Camera API - CAP_OBSENSOR = 2600, //!< For Orbbec 3D-Sensor device/module (Astra+, Femto, Astra2, Gemini2, Gemini2L, Gemini2XL, Gemini330, Femto Mega) attention: Astra2 cameras currently only support Windows and Linux kernel versions no higher than 4.15, and higher versions of Linux kernel may have exceptions. + CAP_OBSENSOR = 2600, //!< For Orbbec 3D-Sensor device/module (Astra+, Femto, Astra2, Gemini2, Gemini2L, Gemini2XL, Femto Mega) attention: Astra2 cameras currently only support Windows and Linux kernel versions no higher than 4.15, and higher versions of Linux kernel may have exceptions. }; @@ -168,7 +168,7 @@ enum VideoCaptureProperties { CAP_PROP_TRIGGER =24, CAP_PROP_TRIGGER_DELAY =25, CAP_PROP_WHITE_BALANCE_RED_V =26, - CAP_PROP_ZOOM =27, //!< Android: May switch physical cameras/lenses. Factor and range are hardware-dependent. + CAP_PROP_ZOOM =27, CAP_PROP_FOCUS =28, CAP_PROP_GUID =29, CAP_PROP_ISO_SPEED =30, @@ -268,7 +268,6 @@ enum VideoAccelerationType VIDEO_ACCELERATION_D3D11 = 2, //!< DirectX 11 VIDEO_ACCELERATION_VAAPI = 3, //!< VAAPI VIDEO_ACCELERATION_MFX = 4, //!< libmfx (Intel MediaSDK/oneVPL) - VIDEO_ACCELERATION_DRM = 5, //!< Raspberry Pi V4 }; //! @} Hardware acceleration support @@ -714,19 +713,6 @@ enum VideoCaptureOBSensorProperties{ CAP_PROP_OBSENSOR_INTRINSIC_FY=26002, CAP_PROP_OBSENSOR_INTRINSIC_CX=26003, CAP_PROP_OBSENSOR_INTRINSIC_CY=26004, - CAP_PROP_OBSENSOR_RGB_POS_MSEC=26005, - CAP_PROP_OBSENSOR_DEPTH_POS_MSEC=26006, - CAP_PROP_OBSENSOR_DEPTH_WIDTH=26007, - CAP_PROP_OBSENSOR_DEPTH_HEIGHT=26008, - CAP_PROP_OBSENSOR_DEPTH_FPS=26009, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K1=26010, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K2=26011, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K3=26012, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K4=26013, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K5=26014, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K6=26015, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1=26016, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_P2=26017 }; //! @} OBSENSOR @@ -740,14 +726,8 @@ class CV_EXPORTS_W IStreamReader public: virtual ~IStreamReader(); - /** @brief Read bytes from stream - * - * @param buffer already allocated buffer of at least @p size bytes - * @param size maximum number of bytes to read - * - * @return actual number of read bytes - */ - CV_WRAP virtual long long read(char* buffer, long long size) = 0; + /** @brief Read bytes from stream */ + virtual long long read(char* buffer, long long size) = 0; /** @brief Sets the stream position * @@ -756,7 +736,7 @@ public: * * @see fseek */ - CV_WRAP virtual long long seek(long long offset, int origin) = 0; + virtual long long seek(long long offset, int origin) = 0; }; class IVideoCapture; diff --git a/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so new file mode 120000 index 0000000000000000000000000000000000000000..aba6a8457b231cd134608eeb59d4cc32361e0c07 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so @@ -0,0 +1 @@ +libopencv_calib3d.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..9cc5b8c6723ae7019b60f747db949e8de93d0c42 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..84e2f9948f745162315c81ce7cd52d41784c889a --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_calib3d.so.411 @@ -0,0 +1 @@ +libopencv_calib3d.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_core.so b/vendor/opensource/opencv/clang/lib/libopencv_core.so new file mode 120000 index 0000000000000000000000000000000000000000..79b403008690b735b2f8093664fa337613ac4ff6 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_core.so @@ -0,0 +1 @@ +libopencv_core.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_core.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_core.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..694e5817bf7f4954a7b3d7f96f1e6d50166a0098 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_core.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_core.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_core.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..ddc2f75416bd55da44585139f894622ed603e01c --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_core.so.411 @@ -0,0 +1 @@ +libopencv_core.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_dnn.so b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so new file mode 120000 index 0000000000000000000000000000000000000000..0d14600a1c9e612114efaf345b023f92e5d68522 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so @@ -0,0 +1 @@ +libopencv_dnn.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_world.so b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so.4.11.0 old mode 100755 new mode 100644 similarity index 31% rename from vendor/opensource/opencv/clang/lib/libopencv_world.so rename to vendor/opensource/opencv/clang/lib/libopencv_dnn.so.4.11.0 index 77271367ec8f6fa4ca1f8a422fa8e3d00c35ad6d..fa3e009f5b61881e98d6dae99ac597d7ce8b720d Binary files a/vendor/opensource/opencv/clang/lib/libopencv_world.so and b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_dnn.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..3a01052ed5f85a82b380363f1637532aa001436c --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_dnn.so.411 @@ -0,0 +1 @@ +libopencv_dnn.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_features2d.so b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so new file mode 120000 index 0000000000000000000000000000000000000000..c344ab85c8a36b9ea060392ef251f6474af768bd --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so @@ -0,0 +1 @@ +libopencv_features2d.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..81aca3ac8f880f243ff63efde14c1fd5fb224865 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..dd06b9198b93951ba6bc2e5095c94a1424ccc7ab --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_features2d.so.411 @@ -0,0 +1 @@ +libopencv_features2d.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_flann.so b/vendor/opensource/opencv/clang/lib/libopencv_flann.so new file mode 120000 index 0000000000000000000000000000000000000000..f72c2ab42db16e9e6e26c7641546c2aebf97e9cd --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_flann.so @@ -0,0 +1 @@ +libopencv_flann.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_flann.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_flann.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..5bf057bf6372d73bca0eb842f7509bfb69d19d75 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_flann.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_flann.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_flann.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..cb3a7f8104c837b91b4ac5439b82df528f3f9bba --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_flann.so.411 @@ -0,0 +1 @@ +libopencv_flann.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_gapi.so b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so new file mode 120000 index 0000000000000000000000000000000000000000..3d3116106cb97f61e40706ca8267b453bb173ae5 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so @@ -0,0 +1 @@ +libopencv_gapi.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..1e3ea3bcd005bc87aa129ae1b866217e4a544227 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..3eda00c8c3a404700832e8f55a8f6d6c846eb317 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_gapi.so.411 @@ -0,0 +1 @@ +libopencv_gapi.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_highgui.so b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so new file mode 120000 index 0000000000000000000000000000000000000000..79536f7063d45a9c135e808eff8bf389970578d2 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so @@ -0,0 +1 @@ +libopencv_highgui.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..42d95d29bd57a1514f9f8f3389ec1611a69936e0 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..7a62afab3c587db5bf4a02576b5877a875c76ea9 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_highgui.so.411 @@ -0,0 +1 @@ +libopencv_highgui.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so new file mode 120000 index 0000000000000000000000000000000000000000..01a776f9a120a5919c040df977c7a0d55e462e6f --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so @@ -0,0 +1 @@ +libopencv_imgcodecs.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..01aa5ea10c0d5140f9f41cfef85342cfd4f765c3 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..83846f50910cf5ee051f2723b070efee9fa2874b --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_imgcodecs.so.411 @@ -0,0 +1 @@ +libopencv_imgcodecs.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so new file mode 120000 index 0000000000000000000000000000000000000000..8b058b7a05391e12ee7e50d8c1c1b001520f3643 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so @@ -0,0 +1 @@ +libopencv_imgproc.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..8b9b519e69375c5704b0da443c0d803647afe511 Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..d5b7300a9b8f0facbb8313a4bcce4e0e979b4fc4 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_imgproc.so.411 @@ -0,0 +1 @@ +libopencv_imgproc.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_ml.so b/vendor/opensource/opencv/clang/lib/libopencv_ml.so new file mode 120000 index 0000000000000000000000000000000000000000..828c4b7e6121c38d1a66183517ad4b31123602d0 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_ml.so @@ -0,0 +1 @@ +libopencv_ml.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_ml.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_ml.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..67944a0c39652b59a29d29b74b4122596e6c9e8d Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_ml.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_ml.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_ml.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..5c43b2ecd5accc1de5076156b3f50f40d8fc809b --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_ml.so.411 @@ -0,0 +1 @@ +libopencv_ml.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so new file mode 120000 index 0000000000000000000000000000000000000000..6dedee5a8b279fd30e09e710d755aa10123c56e9 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so @@ -0,0 +1 @@ +libopencv_objdetect.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..863493746b04e4e901869313cd3b5d1e977183ff Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..120d30078d93f2e42ab1a178f9a54fe3b2867eb2 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_objdetect.so.411 @@ -0,0 +1 @@ +libopencv_objdetect.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_photo.so b/vendor/opensource/opencv/clang/lib/libopencv_photo.so new file mode 120000 index 0000000000000000000000000000000000000000..c58a894d6e8d98748530336ffb22893ceabec9c0 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_photo.so @@ -0,0 +1 @@ +libopencv_photo.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_photo.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_photo.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..0cb11885b58fedfe78dda93977586ab6d97b2ffd Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_photo.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_photo.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_photo.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..fc93078ee8812f47e2ccf06a27c5413949ac2be9 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_photo.so.411 @@ -0,0 +1 @@ +libopencv_photo.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_stitching.so b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so new file mode 120000 index 0000000000000000000000000000000000000000..4888fc1369c06cce3e2658e9f0f5d94726eadaf1 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so @@ -0,0 +1 @@ +libopencv_stitching.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..dda8472fa15f2f5e7dd72c4efbbe9ddfaf76d7cc Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..762025e2d98b26d3615511ebbdab11e2e3ba5489 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_stitching.so.411 @@ -0,0 +1 @@ +libopencv_stitching.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_video.so b/vendor/opensource/opencv/clang/lib/libopencv_video.so new file mode 120000 index 0000000000000000000000000000000000000000..28b6465266b7c7174f1665028b4e5de3d8a3e535 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_video.so @@ -0,0 +1 @@ +libopencv_video.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_video.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_video.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..5b315725c3ed5cb7e408f1b39e18ef1150874b3c Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_video.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_video.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_video.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..01e1770392e6ae671e41da2dd158a6005f534a2e --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_video.so.411 @@ -0,0 +1 @@ +libopencv_video.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_videoio.so b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so new file mode 120000 index 0000000000000000000000000000000000000000..1322287ccc886833a3fdbbf974377f354527ef48 --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so @@ -0,0 +1 @@ +libopencv_videoio.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.4.11.0 b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..573d5362e08598d85804f373ce4ded0848291d4f Binary files /dev/null and b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.4.11.0 differ diff --git a/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.411 b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..e5a6a328015d564808e562f8d7a52b0982a5a31f --- /dev/null +++ b/vendor/opensource/opencv/clang/lib/libopencv_videoio.so.411 @@ -0,0 +1 @@ +libopencv_videoio.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/calib3d.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/calib3d.hpp index b66fec1e0466175783018bd561fe6e3474ed6229..f44dacbedf9d0394767aa76aba1ad18ef99345af 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/calib3d.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/calib3d.hpp @@ -383,110 +383,6 @@ R & t \\ 0 & 1 \end{bmatrix} P_{h_0}.\f] - Homogeneous Transformations, Object frame / Camera frame
-Change of basis or computing the 3D coordinates from one frame to another frame can be achieved easily using -the following notation: - -\f[ -\mathbf{X}_c = \hspace{0.2em} -{}^{c}\mathbf{T}_o \hspace{0.2em} \mathbf{X}_o -\f] - -\f[ -\begin{bmatrix} -X_c \\ -Y_c \\ -Z_c \\ -1 -\end{bmatrix} = -\begin{bmatrix} -{}^{c}\mathbf{R}_o & {}^{c}\mathbf{t}_o \\ -0_{1 \times 3} & 1 -\end{bmatrix} -\begin{bmatrix} -X_o \\ -Y_o \\ -Z_o \\ -1 -\end{bmatrix} -\f] - -For a 3D points (\f$ \mathbf{X}_o \f$) expressed in the object frame, the homogeneous transformation matrix -\f$ {}^{c}\mathbf{T}_o \f$ allows computing the corresponding coordinate (\f$ \mathbf{X}_c \f$) in the camera frame. -This transformation matrix is composed of a 3x3 rotation matrix \f$ {}^{c}\mathbf{R}_o \f$ and a 3x1 translation vector -\f$ {}^{c}\mathbf{t}_o \f$. -The 3x1 translation vector \f$ {}^{c}\mathbf{t}_o \f$ is the position of the object frame in the camera frame and the -3x3 rotation matrix \f$ {}^{c}\mathbf{R}_o \f$ the orientation of the object frame in the camera frame. - -With this simple notation, it is easy to chain the transformations. For instance, to compute the 3D coordinates of a point -expressed in the object frame in the world frame can be done with: - -\f[ -\mathbf{X}_w = \hspace{0.2em} -{}^{w}\mathbf{T}_c \hspace{0.2em} {}^{c}\mathbf{T}_o \hspace{0.2em} -\mathbf{X}_o = -{}^{w}\mathbf{T}_o \hspace{0.2em} \mathbf{X}_o -\f] - -Similarly, computing the inverse transformation can be done with: - -\f[ -\mathbf{X}_o = \hspace{0.2em} -{}^{o}\mathbf{T}_c \hspace{0.2em} \mathbf{X}_c = -\left( {}^{c}\mathbf{T}_o \right)^{-1} \hspace{0.2em} \mathbf{X}_c -\f] - -The inverse of an homogeneous transformation matrix is then: - -\f[ -{}^{o}\mathbf{T}_c = \left( {}^{c}\mathbf{T}_o \right)^{-1} = -\begin{bmatrix} -{}^{c}\mathbf{R}^{\top}_o & - \hspace{0.2em} {}^{c}\mathbf{R}^{\top}_o \hspace{0.2em} {}^{c}\mathbf{t}_o \\ -0_{1 \times 3} & 1 -\end{bmatrix} -\f] - -One can note that the inverse of a 3x3 rotation matrix is directly its matrix transpose. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png) - -This figure summarizes the whole process. The object pose returned for instance by the @ref solvePnP function -or pose from fiducial marker detection is this \f$ {}^{c}\mathbf{T}_o \f$ transformation. - -The camera intrinsic matrix \f$ \mathbf{K} \f$ allows projecting the 3D point expressed in the camera frame onto the image plane -assuming a perspective projection model (pinhole camera model). Image coordinates extracted from classical image processing functions -assume a (u,v) top-left coordinates frame. - -\note -- for an online video course on this topic, see for instance: - - ["3.3.1. Homogeneous Transformation Matrices", Modern Robotics, Kevin M. Lynch and Frank C. Park](https://modernrobotics.northwestern.edu/nu-gm-book-resource/3-3-1-homogeneous-transformation-matrices/) -- the 3x3 rotation matrix is composed of 9 values but describes a 3 dof transformation -- some additional properties of the 3x3 rotation matrix are: - - \f$ \mathrm{det} \left( \mathbf{R} \right) = 1 \f$ - - \f$ \mathbf{R} \mathbf{R}^{\top} = \mathbf{R}^{\top} \mathbf{R} = \mathrm{I}_{3 \times 3} \f$ - - interpolating rotation can be done using the [Slerp (spherical linear interpolation)](https://en.wikipedia.org/wiki/Slerp) method -- quick conversions between the different rotation formalisms can be done using this [online tool](https://www.andre-gaschler.com/rotationconverter/) - - Intrinsic parameters from camera lens specifications
-When dealing with industrial cameras, the camera intrinsic matrix or more precisely \f$ \left(f_x, f_y \right) \f$ -can be deduced, approximated from the camera specifications: - -\f[ -f_x = \frac{f_{\text{mm}}}{\text{pixel_size_in_mm}} = \frac{f_{\text{mm}}}{\text{sensor_size_in_mm} / \text{nb_pixels}} -\f] - -In a same way, the physical focal length can be deduced from the angular field of view: - -\f[ -f_{\text{mm}} = \frac{\text{sensor_size_in_mm}}{2 \times \tan{\frac{\text{fov}}{2}}} -\f] - -This latter conversion can be useful when using a rendering software to mimic a physical camera device. - -@note - - See also #calibrationMatrixValues - - Additional references, notes
@note - Many functions in this module take a camera intrinsic matrix as an input parameter. Although all functions assume the same structure of this parameter, they may name it differently. The @@ -565,7 +461,7 @@ enum SolvePnPMethod { //!< Initial solution for non-planar "objectPoints" needs at least 6 points and uses the DLT algorithm. \n //!< Initial solution for planar "objectPoints" needs at least 4 points and uses pose from homography decomposition. SOLVEPNP_EPNP = 1, //!< EPnP: Efficient Perspective-n-Point Camera Pose Estimation @cite lepetit2009epnp - SOLVEPNP_P3P = 2, //!< Revisiting the P3P Problem @cite ding2023revisiting + SOLVEPNP_P3P = 2, //!< Complete Solution Classification for the Perspective-Three-Point Problem @cite gao2003complete SOLVEPNP_DLS = 3, //!< **Broken implementation. Using this flag will fallback to EPnP.** \n //!< A Direct Least-Squares (DLS) Method for PnP @cite hesch2011direct SOLVEPNP_UPNP = 4, //!< **Broken implementation. Using this flag will fallback to EPnP.** \n @@ -1002,9 +898,7 @@ An example program about homography from the camera displacement Check @ref tutorial_homography "the corresponding tutorial" for more details */ -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences: - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1059,8 +953,7 @@ More information about Perspective-n-Points is described in @ref calib3d_solvePn of the P3P problem, the last one is used to retain the best solution that minimizes the reprojection error). - With @ref SOLVEPNP_ITERATIVE method and `useExtrinsicGuess=true`, the minimum number of points is 3 (3 points are sufficient to compute a pose but there are up to 4 solutions). The initial solution should be close to the - global solution to converge. The function returns true if some solution is found. User code is responsible for - solution quality assessment. + global solution to converge. - With @ref SOLVEPNP_IPPE input points must be >= 4 and object points must be coplanar. - With @ref SOLVEPNP_IPPE_SQUARE this is a special case suitable for marker pose estimation. Number of input points must be 4. Object points must be defined in the following order: @@ -1068,16 +961,14 @@ More information about Perspective-n-Points is described in @ref calib3d_solvePn - point 1: [ squareLength / 2, squareLength / 2, 0] - point 2: [ squareLength / 2, -squareLength / 2, 0] - point 3: [-squareLength / 2, -squareLength / 2, 0] - - With @ref SOLVEPNP_SQPNP input points must be >= 3 + - With @ref SOLVEPNP_SQPNP input points must be >= 3 */ CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE ); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences using the RANSAC scheme to deal with bad matches. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme. @see @ref calib3d_solvePnP @@ -1110,8 +1001,8 @@ projections imagePoints and the projected (using @ref projectPoints ) objectPoin makes the function resistant to outliers. @note - - An example of how to use solvePnPRansac for object detection can be found at - @ref tutorial_real_time_pose + - An example of how to use solvePNPRansac for object detection can be found at + opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/ - The default method used to estimate the camera pose for the Minimal Sample Sets step is #SOLVEPNP_EPNP. Exceptions are: - if you choose #SOLVEPNP_P3P or #SOLVEPNP_AP3P, these methods will be used. @@ -1137,9 +1028,7 @@ CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoint OutputArray rvec, OutputArray tvec, OutputArray inliers, const UsacParams ¶ms=UsacParams()); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from **3** 3D-2D point correspondences. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1155,8 +1044,8 @@ assumed. the model coordinate system to the camera coordinate system. A P3P problem has up to 4 solutions. @param tvecs Output translation vectors. @param flags Method for solving a P3P problem: -- @ref SOLVEPNP_P3P Method is based on the paper of Ding, Y., Yang, J., Larsson, V., Olsson, C., & Åstrom, K. -"Revisiting the P3P Problem" (@cite ding2023revisiting). +- @ref SOLVEPNP_P3P Method is based on the paper of X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang +"Complete Solution Classification for the Perspective-Three-Point Problem" (@cite gao2003complete). - @ref SOLVEPNP_AP3P Method is based on the paper of T. Ke and S. Roumeliotis. "An Efficient Algebraic Solution to the Perspective-Three-Point Problem" (@cite Ke17). @@ -1232,9 +1121,7 @@ CV_EXPORTS_W void solvePnPRefineVVS( InputArray objectPoints, InputArray imagePo TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON), double VVSlambda = 1); -/** @brief Finds an object pose \f$ {}^{c}\mathbf{T}_o \f$ from 3D-2D point correspondences. - -![Perspective projection, from object to camera frame](pics/pinhole_homogeneous_transformation.png){ width=50% } +/** @brief Finds an object pose from 3D-2D point correspondences. @see @ref calib3d_solvePnP @@ -1305,7 +1192,6 @@ More information is described in @ref calib3d_solvePnP - point 1: [ squareLength / 2, squareLength / 2, 0] - point 2: [ squareLength / 2, -squareLength / 2, 0] - point 3: [-squareLength / 2, -squareLength / 2, 0] - - With @ref SOLVEPNP_SQPNP input points must be >= 3 */ CV_EXPORTS_W int solvePnPGeneric( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, @@ -1386,8 +1272,7 @@ the board to make the detection more robust in various environments. Otherwise, border and the background is dark, the outer black squares cannot be segmented properly and so the square grouping and ordering algorithm fails. -Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the desired checkerboard pattern. +Use gen_pattern.py (@ref tutorial_camera_calibration_pattern) to create checkerboard. */ CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); @@ -1411,7 +1296,7 @@ CV_EXPORTS_W bool checkChessboard(InputArray img, Size size); - @ref CALIB_CB_LARGER The detected pattern is allowed to be larger than patternSize (see description). - @ref CALIB_CB_MARKER The detected pattern must have a marker (see description). This should be used if an accurate camera calibration is required. -@param meta Optional output array of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). +@param meta Optional output arrray of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). Each entry stands for one corner of the pattern and can have one of the following values: - 0 = no meta data attached - 1 = left-top corner of a black cell @@ -1445,9 +1330,8 @@ which are located on the outside of the board. The following figure illustrates a sample checkerboard optimized for the detection. However, any other checkerboard can be used as well. -Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern) -to create the corresponding checkerboard pattern: -\image html pics/checkerboard_radon.png width=60% +Use gen_pattern.py (@ref tutorial_camera_calibration_pattern) to create checkerboard. +![Checkerboard](pics/checkerboard_radon.png) */ CV_EXPORTS_AS(findChessboardCornersSBWithMeta) bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, @@ -1550,7 +1434,7 @@ struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters { SYMMETRIC_GRID, ASYMMETRIC_GRID }; - CV_PROP_RW GridType gridType; + GridType gridType; CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. @@ -3363,78 +3247,6 @@ CV_EXPORTS_W cv::Mat estimateAffinePartial2D(InputArray from, InputArray to, Out size_t maxIters = 2000, double confidence = 0.99, size_t refineIters = 10); -/** @brief Computes a pure 2D translation between two 2D point sets. - -It computes -\f[ -\begin{bmatrix} -x\\ -y -\end{bmatrix} -= -\begin{bmatrix} -1 & 0\\ -0 & 1 -\end{bmatrix} -\begin{bmatrix} -X\\ -Y -\end{bmatrix} -+ -\begin{bmatrix} -t_x\\ -t_y -\end{bmatrix}. -\f] - -@param from First input 2D point set containing \f$(X,Y)\f$. -@param to Second input 2D point set containing \f$(x,y)\f$. -@param inliers Output vector indicating which points are inliers (1-inlier, 0-outlier). -@param method Robust method used to compute the transformation. The following methods are possible: -- @ref RANSAC - RANSAC-based robust method -- @ref LMEDS - Least-Median robust method -RANSAC is the default method. -@param ransacReprojThreshold Maximum reprojection error in the RANSAC algorithm to consider -a point as an inlier. Applies only to RANSAC. -@param maxIters The maximum number of robust method iterations. -@param confidence Confidence level, between 0 and 1, for the estimated transformation. Anything -between 0.95 and 0.99 is usually good enough. Values too close to 1 can slow down the estimation -significantly. Values lower than 0.8–0.9 can result in an incorrectly estimated transformation. -@param refineIters Maximum number of iterations of the refining algorithm. For pure translation -the least-squares solution on inliers is closed-form, so passing 0 is recommended (no additional refine). - -@return A 2D translation vector \f$[t_x, t_y]^T\f$ as `cv::Vec2d`. If the translation could not be -estimated, both components are set to NaN and, if @p inliers is provided, the mask is filled with zeros. - -\par Converting to a 2x3 transformation matrix: -\f[ -\begin{bmatrix} -1 & 0 & t_x\\ -0 & 1 & t_y -\end{bmatrix} -\f] - -@code{.cpp} -cv::Vec2d t = cv::estimateTranslation2D(from, to, inliers); -cv::Mat T = (cv::Mat_(2,3) << 1,0,t[0], 0,1,t[1]); -@endcode - -The function estimates a pure 2D translation between two 2D point sets using the selected robust -algorithm. Inliers are determined by the reprojection error threshold. - -@note -The RANSAC method can handle practically any ratio of outliers but needs a threshold to -distinguish inliers from outliers. The method LMeDS does not need any threshold but works -correctly only when there are more than 50% inliers. - -@sa estimateAffine2D, estimateAffinePartial2D, getAffineTransform -*/ -CV_EXPORTS_W cv::Vec2d estimateTranslation2D(InputArray from, InputArray to, OutputArray inliers = noArray(), - int method = RANSAC, - double ransacReprojThreshold = 3, - size_t maxIters = 2000, double confidence = 0.99, - size_t refineIters = 0); - /** @example samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp An example program with homography decomposition. @@ -3534,136 +3346,52 @@ public: }; -/** - * @brief Class for computing stereo correspondence using the block matching algorithm, introduced and contributed to OpenCV by K. Konolige. - * @details This class implements a block matching algorithm for stereo correspondence, which is used to compute disparity maps from stereo image pairs. It provides methods to fine-tune parameters such as pre-filtering, texture thresholds, uniqueness ratios, and regions of interest (ROIs) to optimize performance and accuracy. +/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and +contributed to OpenCV by K. Konolige. */ class CV_EXPORTS_W StereoBM : public StereoMatcher { public: - /** - * @brief Pre-filter types for the stereo matching algorithm. - * @details These constants define the type of pre-filtering applied to the images before computing the disparity map. - * - PREFILTER_NORMALIZED_RESPONSE: Uses normalized response for pre-filtering. - * - PREFILTER_XSOBEL: Uses the X-Sobel operator for pre-filtering. - */ - enum { - PREFILTER_NORMALIZED_RESPONSE = 0, ///< Normalized response pre-filter - PREFILTER_XSOBEL = 1 ///< X-Sobel pre-filter - }; + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; - /** - * @brief Gets the type of pre-filtering currently used in the algorithm. - * @return The current pre-filter type: 0 for PREFILTER_NORMALIZED_RESPONSE or 1 for PREFILTER_XSOBEL. - */ CV_WRAP virtual int getPreFilterType() const = 0; - - /** - * @brief Sets the type of pre-filtering used in the algorithm. - * @param preFilterType The type of pre-filter to use. Possible values are: - * - PREFILTER_NORMALIZED_RESPONSE (0): Uses normalized response for pre-filtering. - * - PREFILTER_XSOBEL (1): Uses the X-Sobel operator for pre-filtering. - * @details The pre-filter type affects how the images are prepared before computing the disparity map. Different pre-filtering methods can enhance specific image features or reduce noise, influencing the quality of the disparity map. - */ CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; - /** - * @brief Gets the current size of the pre-filter kernel. - * @return The current pre-filter size. - */ CV_WRAP virtual int getPreFilterSize() const = 0; - - /** - * @brief Sets the size of the pre-filter kernel. - * @param preFilterSize The size of the pre-filter kernel. Must be an odd integer, typically between 5 and 255. - * @details The pre-filter size determines the spatial extent of the pre-filtering operation, which prepares the images for disparity computation by normalizing brightness and enhancing texture. Larger sizes reduce noise but may blur details, while smaller sizes preserve details but are more susceptible to noise. - */ CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; - /** - * @brief Gets the current truncation value for prefiltered pixels. - * @return The current pre-filter cap value. - */ CV_WRAP virtual int getPreFilterCap() const = 0; - - /** - * @brief Sets the truncation value for prefiltered pixels. - * @param preFilterCap The truncation value. Typically in the range [1, 63]. - * @details This value caps the output of the pre-filter to [-preFilterCap, preFilterCap], helping to reduce the impact of noise and outliers in the pre-filtered image. - */ CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; - /** - * @brief Gets the current texture threshold value. - * @return The current texture threshold. - */ CV_WRAP virtual int getTextureThreshold() const = 0; - - /** - * @brief Sets the threshold for filtering low-texture regions. - * @param textureThreshold The threshold value. Must be non-negative. - * @details This parameter filters out regions with low texture, where establishing correspondences is difficult, thus reducing noise in the disparity map. Higher values filter more aggressively but may discard valid information. - */ CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; - /** - * @brief Gets the current uniqueness ratio value. - * @return The current uniqueness ratio. - */ CV_WRAP virtual int getUniquenessRatio() const = 0; - - /** - * @brief Sets the uniqueness ratio for filtering ambiguous matches. - * @param uniquenessRatio The uniqueness ratio value. Typically in the range [5, 15], but can be from 0 to 100. - * @details This parameter ensures that the best match is sufficiently better than the next best match, reducing false positives. Higher values are stricter but may filter out valid matches in difficult regions. - */ CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; - /** - * @brief Gets the current size of the smaller block used for texture check. - * @return The current smaller block size. - */ CV_WRAP virtual int getSmallerBlockSize() const = 0; - - /** - * @brief Sets the size of the smaller block used for texture check. - * @param blockSize The size of the smaller block. Must be an odd integer between 5 and 255. - * @details This parameter determines the size of the block used to compute texture variance. Smaller blocks capture finer details but are more sensitive to noise, while larger blocks are more robust but may miss fine details. - */ CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; - /** - * @brief Gets the current Region of Interest (ROI) for the left image. - * @return The current ROI for the left image. - */ CV_WRAP virtual Rect getROI1() const = 0; - - /** - * @brief Sets the Region of Interest (ROI) for the left image. - * @param roi1 The ROI rectangle for the left image. - * @details By setting the ROI, the stereo matching computation is limited to the specified region, improving performance and potentially accuracy by focusing on relevant parts of the image. - */ CV_WRAP virtual void setROI1(Rect roi1) = 0; - /** - * @brief Gets the current Region of Interest (ROI) for the right image. - * @return The current ROI for the right image. - */ CV_WRAP virtual Rect getROI2() const = 0; - - /** - * @brief Sets the Region of Interest (ROI) for the right image. - * @param roi2 The ROI rectangle for the right image. - * @details Similar to setROI1, this limits the computation to the specified region in the right image. - */ CV_WRAP virtual void setROI2(Rect roi2) = 0; - /** - * @brief Creates StereoBM object - * @param numDisparities The disparity search range. For each pixel, the algorithm will find the best disparity from 0 (default minimum disparity) to numDisparities. The search range can be shifted by changing the minimum disparity. - * @param blockSize The linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is a higher chance for the algorithm to find a wrong correspondence. - * @return A pointer to the created StereoBM object. - * @details The function creates a StereoBM object. You can then call StereoBM::compute() to compute disparity for a specific stereo pair. + /** @brief Creates StereoBM object + + @param numDisparities the disparity search range. For each pixel algorithm will find the best + disparity from 0 (default minimum disparity) to numDisparities. The search range can then be + shifted by changing the minimum disparity. + @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd + (as the block is centered at the current pixel). Larger block size implies smoother, though less + accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher + chance for algorithm to find a wrong correspondence. + + The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for + a specific stereo pair. */ CV_WRAP static Ptr create(int numDisparities = 0, int blockSize = 21); }; @@ -4042,7 +3770,8 @@ CV_64FC2) (or vector\ ). CV_EXPORTS_W void undistortImagePoints(InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray distCoeffs, - TermCriteria = TermCriteria(TermCriteria::MAX_ITER, 5, 0.01)); + TermCriteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, + 0.01)); //! @} calib3d @@ -4168,7 +3897,7 @@ namespace fisheye may additionally scale and shift the result by using a different matrix. @param new_size the new size - The function transforms an image to compensate radial lens distortion. + The function transforms an image to compensate radial and tangential lens distortion. The function is simply a combination of #fisheye::initUndistortRectifyMap (with unity R ) and #remap (with bilinear interpolation). See the former function for details of the transformation being @@ -4331,35 +4060,7 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); /** - @brief Finds an object pose from 3D-2D point correspondences for fisheye camera model. - - @param objectPoints Array of object points in the object coordinate space, Nx3 1-channel or - 1xN/Nx1 3-channel, where N is the number of points. vector\ can also be passed here. - @param imagePoints Array of corresponding image points, Nx2 1-channel or 1xN/Nx1 2-channel, - where N is the number of points. vector\ can also be passed here. - @param cameraMatrix Input camera intrinsic matrix \f$\cameramatrix{A}\f$ . - @param distCoeffs Input vector of distortion coefficients (4x1/1x4). - @param rvec Output rotation vector (see @ref Rodrigues ) that, together with tvec, brings points from - the model coordinate system to the camera coordinate system. - @param tvec Output translation vector. - @param useExtrinsicGuess Parameter used for #SOLVEPNP_ITERATIVE. If true (1), the function uses - the provided rvec and tvec values as initial approximations of the rotation and translation - vectors, respectively, and further optimizes them. - @param flags Method for solving a PnP problem: see @ref calib3d_solvePnP_flags - @param criteria Termination criteria for internal undistortPoints call. - The function internally undistorts points with @ref undistortPoints and call @ref cv::solvePnP, - thus the input are very similar. More information about Perspective-n-Points is described in @ref calib3d_solvePnP - for more information. - */ - CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, - InputArray cameraMatrix, InputArray distCoeffs, - OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) - ); - - /** - @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme for fisheye camera moodel. + @brief Finds an object pose from 3D-2D point correspondences for fisheye camera moodel. @param objectPoints Array of object points in the object coordinate space, Nx3 1-channel or 1xN/Nx1 3-channel, where N is the number of points. vector\ can be also passed here. @@ -4373,12 +4074,6 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ @param useExtrinsicGuess Parameter used for #SOLVEPNP_ITERATIVE. If true (1), the function uses the provided rvec and tvec values as initial approximations of the rotation and translation vectors, respectively, and further optimizes them. - @param iterationsCount Number of iterations. - @param reprojectionError Inlier threshold value used by the RANSAC procedure. The parameter value - is the maximum allowed distance between the observed and computed point projections to consider it - an inlier. - @param confidence The probability that the algorithm produces a useful result. - @param inliers Output vector that contains indices of inliers in objectPoints and imagePoints . @param flags Method for solving a PnP problem: see @ref calib3d_solvePnP_flags This function returns the rotation and the translation vectors that transform a 3D point expressed in the object coordinate frame to the camera coordinate frame, using different methods: @@ -4396,14 +4091,12 @@ optimization. It is the \f$max(width,height)/\pi\f$ or the provided \f$f_x\f$, \ thus the input are very similar. More information about Perspective-n-Points is described in @ref calib3d_solvePnP for more information. */ - CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints, - InputArray cameraMatrix, InputArray distCoeffs, - OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess = false, int iterationsCount = 100, - float reprojectionError = 8.0, double confidence = 0.99, - OutputArray inliers = noArray(), int flags = SOLVEPNP_ITERATIVE, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) - ); + CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray rvec, OutputArray tvec, + bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE, + TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 1e-8) + ); //! @} calib3d_fisheye } // end namespace fisheye diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core.hpp index e3836523d5226d4cb8005f5a2a2285ba8f3c48a6..dcbdfda08e7209f708e5fefc9365a3da6a3ed970 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core.hpp @@ -57,6 +57,10 @@ #include "opencv2/core/types.hpp" #include "opencv2/core/mat.hpp" #include "opencv2/core/persistence.hpp" +#include "opencv2/core/cust_meta_data_of_mem_block.h" +#include "opencv2/core/cust_log.h" +#include "opencv2/core/cust_mpp_allocator.h" +#include "opencv2/core/cust_init_and_final.h" /** @defgroup core Core functionality @@ -540,9 +544,9 @@ The function LUT fills the output array with values from the look-up table. Indi are taken from the input array. That is, the function processes each element of src as follows: \f[\texttt{dst} (I) \leftarrow \texttt{lut(src(I) + d)}\f] where -\f[d = \forkthree{0}{if \(\texttt{src}\) has depth \(\texttt{CV_8U}\) or \(\texttt{CV_16U}\)}{128}{if \(\texttt{src}\) has depth \(\texttt{CV_8S}\)}{32768}{if \(\texttt{src}\) has depth \(\texttt{CV_16S}\)}\f] -@param src input array of 8-bit or 16-bit integer elements. -@param lut look-up table of 256 elements (if src has depth CV_8U or CV_8S) or 65536 elements(if src has depth CV_16U or CV_16S); in case of multi-channel input array, the table should +\f[d = \fork{0}{if \(\texttt{src}\) has depth \(\texttt{CV_8U}\)}{128}{if \(\texttt{src}\) has depth \(\texttt{CV_8S}\)}\f] +@param src input array of 8-bit elements. +@param lut look-up table of 256 elements; in case of multi-channel input array, the table should either have a single channel (in this case the same table is used for all channels) or the same number of channels as in the input array. @param dst output array of the same size and number of channels as src, and the same depth as lut. @@ -805,11 +809,6 @@ Possible usage with some positive example data: normalize(positiveData, normalizedData_minmax, 1.0, 0.0, NORM_MINMAX); @endcode -@note Due to rounding issues, min-max normalization can result in values outside provided boundaries. -If exact range conformity is needed, following workarounds can be used: -- use double floating point precision (dtype = CV_64F) -- manually clip values (`cv::max(res, left_bound, res)`, `cv::min(res, right_bound, res)` or `np.clip`) - @param src input array. @param dst output array of the same size as src . @param alpha norm value to normalize to or the lower range boundary in case of the range @@ -1711,13 +1710,10 @@ elements. */ CV_EXPORTS_W bool checkRange(InputArray a, bool quiet = true, CV_OUT Point* pos = 0, double minVal = -DBL_MAX, double maxVal = DBL_MAX); -/** @brief Replaces NaNs (Not-a-Number values) in a matrix with the specified value. - -This function modifies the input matrix in-place. -The input matrix must be of type `CV_32F` or `CV_64F`; other types are not supported. -@param a Input/output matrix (CV_32F or CV_64F type). -@param val Value used to replace NaNs (defaults to 0). +/** @brief Replaces NaNs by given number +@param a input/output matrix (CV_32F type). +@param val value to convert the NaNs */ CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val = 0); @@ -2012,8 +2008,8 @@ The function solveCubic finds the real roots of a cubic equation: The roots are stored in the roots array. @param coeffs equation coefficients, an array of 3 or 4 elements. -@param roots output array of real roots that has 0, 1, 2 or 3 elements. -@return number of real roots. It can be -1 (all real numbers), 0, 1, 2 or 3. +@param roots output array of real roots that has 1 or 3 elements. +@return number of real roots. It can be 0, 1 or 2. */ CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots); diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/base.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/base.hpp index e295a5f7e143a0b7e832212b95452b128a58e431..5e63ae370035e3ab39348e1de4fb17ed15ad1231 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/base.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/base.hpp @@ -263,72 +263,8 @@ enum DftFlags { DCT_ROWS = DFT_ROWS }; -/*! Various border types, image boundaries are denoted with the `|` character in the table below, when describing each method. - -The following examples show the result of the @ref copyMakeBorder call according to different methods. -Input image is `6x4` (width x height) size and the @ref copyMakeBorder function is used with a border size of 2 pixels -in each direction, giving a resulting image of `10x8` resolution. - -@code -Input image: -[[ 0 1 2 3 4 5] - [ 6 7 8 9 10 11] - [12 13 14 15 16 17] - [18 19 20 21 22 23]] - -Border type: BORDER_CONSTANT (a constant value of 255 is used) -[[255 255 255 255 255 255 255 255 255 255] - [255 255 255 255 255 255 255 255 255 255] - [255 255 0 1 2 3 4 5 255 255] - [255 255 6 7 8 9 10 11 255 255] - [255 255 12 13 14 15 16 17 255 255] - [255 255 18 19 20 21 22 23 255 255] - [255 255 255 255 255 255 255 255 255 255] - [255 255 255 255 255 255 255 255 255 255]] - -Border type: BORDER_REPLICATE -[[ 0 0 0 1 2 3 4 5 5 5] - [ 0 0 0 1 2 3 4 5 5 5] - [ 0 0 0 1 2 3 4 5 5 5] - [ 6 6 6 7 8 9 10 11 11 11] - [12 12 12 13 14 15 16 17 17 17] - [18 18 18 19 20 21 22 23 23 23] - [18 18 18 19 20 21 22 23 23 23] - [18 18 18 19 20 21 22 23 23 23]] - -Border type: BORDER_REFLECT -[[ 7 6 6 7 8 9 10 11 11 10] - [ 1 0 0 1 2 3 4 5 5 4] - [ 1 0 0 1 2 3 4 5 5 4] - [ 7 6 6 7 8 9 10 11 11 10] - [13 12 12 13 14 15 16 17 17 16] - [19 18 18 19 20 21 22 23 23 22] - [19 18 18 19 20 21 22 23 23 22] - [13 12 12 13 14 15 16 17 17 16]] - -Border type: BORDER_WRAP -[[16 17 12 13 14 15 16 17 12 13] - [22 23 18 19 20 21 22 23 18 19] - [ 4 5 0 1 2 3 4 5 0 1] - [10 11 6 7 8 9 10 11 6 7] - [16 17 12 13 14 15 16 17 12 13] - [22 23 18 19 20 21 22 23 18 19] - [ 4 5 0 1 2 3 4 5 0 1] - [10 11 6 7 8 9 10 11 6 7]] - -Border type: BORDER_REFLECT_101 -[[14 13 12 13 14 15 16 17 16 15] - [ 8 7 6 7 8 9 10 11 10 9] - [ 2 1 0 1 2 3 4 5 4 3] - [ 8 7 6 7 8 9 10 11 10 9] - [14 13 12 13 14 15 16 17 16 15] - [20 19 18 19 20 21 22 23 22 21] - [14 13 12 13 14 15 16 17 16 15] - [ 8 7 6 7 8 9 10 11 10 9]] -@endcode - -@see borderInterpolate, copyMakeBorder - */ +//! Various border types, image boundaries are denoted with `|` +//! @see borderInterpolate, copyMakeBorder enum BorderTypes { BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i` BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh` @@ -450,7 +386,7 @@ It does not throw exception, but terminates the application. //! @endcond -#if !defined(NDEBUG) || defined(CV_STATIC_ANALYSIS) +#if defined _DEBUG || defined CV_STATIC_ANALYSIS # define CV_DbgAssert(expr) CV_Assert(expr) #else /** replaced with CV_Assert(expr) in Debug configuration */ @@ -698,7 +634,6 @@ namespace ogl namespace cuda { class CV_EXPORTS GpuMat; - class CV_EXPORTS GpuMatND; class CV_EXPORTS HostMem; class CV_EXPORTS Stream; class CV_EXPORTS Event; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/bindings_utils.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/bindings_utils.hpp index dd00b59ffdb819ef416a956b0c61fb46c83da143..9c8f9e0f2bce39ebe04401a9658c1af270f59ad7 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/bindings_utils.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/bindings_utils.hpp @@ -335,6 +335,23 @@ namespace fs { //! @} // core_utils } // namespace cv::utils +//! @cond IGNORED + +CV_WRAP static inline +int setLogLevel(int level) +{ + // NB: Binding generators doesn't work with enums properly yet, so we define separate overload here + return cv::utils::logging::setLogLevel((cv::utils::logging::LogLevel)level); +} + +CV_WRAP static inline +int getLogLevel() +{ + return cv::utils::logging::getLogLevel(); +} + +//! @endcond IGNORED + } // namespaces cv / utils #endif // OPENCV_CORE_BINDINGS_UTILS_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda.hpp index 76b8e6bff1917fbb694dd9b9eeace2dacd6222e7..8191c00783a5c4a4c9d6f32911ab05de2af80c32 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda.hpp @@ -240,10 +240,6 @@ public: //! converts GpuMat to another datatype (Blocking call) void convertTo(OutputArray dst, int rtype) const; - //! bindings overload which converts GpuMat to another datatype (Blocking call) - CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype) const { - convertTo(static_cast(dst), rtype); - } //! converts GpuMat to another datatype (Non-Blocking call) void convertTo(OutputArray dst, int rtype, Stream& stream) const; @@ -254,13 +250,10 @@ public: //! converts GpuMat to another datatype with scaling (Blocking call) void convertTo(OutputArray dst, int rtype, double alpha, double beta = 0.0) const; - //! bindings overload which converts GpuMat to another datatype with scaling(Blocking call) -#ifdef OPENCV_BINDINGS_PARSER - CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype, double alpha=1.0, double beta = 0.0) const { + CV_WRAP void convertTo(CV_OUT GpuMat& dst, int rtype, double alpha = 1.0, double beta = 0.0) const { convertTo(static_cast(dst), rtype, alpha, beta); } -#endif //! converts GpuMat to another datatype with scaling (Non-Blocking call) void convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/cuda_compat.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/cuda_compat.hpp deleted file mode 100644 index b40b2ea4f9e8e42baa08f5464b6be0fa8b3ee417..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/cuda_compat.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html. - -#ifndef OPENCV_CUDA_CUDA_COMPAT_HPP -#define OPENCV_CUDA_CUDA_COMPAT_HPP - -#include - -namespace cv { namespace cuda { namespace device { namespace compat -{ -#if CUDA_VERSION >= 13000 - using ulonglong4 = ::ulonglong4_16a; - using double4 = ::double4_16a; - __host__ __device__ __forceinline__ - double4 make_double4(double x, double y, double z, double w) - { - return ::make_double4_16a(x, y, z, w); - } -#else - using ulonglong4 = ::ulonglong4; - using double4 = ::double4; - __host__ __device__ __forceinline__ - double4 make_double4(double x, double y, double z, double w) - { - return ::make_double4(x, y, z, w); - } -#endif - using ulonglong4Compat = ulonglong4; - using double4Compat = double4; - __host__ __device__ __forceinline__ - double4Compat make_double4_compat(double x, double y, double z, double w) - { - return make_double4(x, y, z, w); - } -}}}} - -#endif // OPENCV_CUDA_CUDA_COMPAT_HPP \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_math.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_math.hpp index afb8cc0c4c700a2a387df8fb5b514e428282213e..80b130368187ea6b15aab5c3ffb32b8cbcacbfd8 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_math.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_math.hpp @@ -45,7 +45,6 @@ #include "vec_traits.hpp" #include "saturate_cast.hpp" -#include "cuda_compat.hpp" /** @file * @deprecated Use @ref cudev instead. @@ -55,8 +54,6 @@ namespace cv { namespace cuda { namespace device { - using cv::cuda::device::compat::double4; - using cv::cuda::device::compat::make_double4; // saturate_cast diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_traits.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_traits.hpp index 786a9314a7a24fe7af73eeb125e666f963a587b6..b5ff281a0b8a3b7c5a6a481fa7880b7f24e4786f 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_traits.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cuda/vec_traits.hpp @@ -44,7 +44,6 @@ #define OPENCV_CUDA_VEC_TRAITS_HPP #include "common.hpp" -#include "cuda_compat.hpp" /** @file * @deprecated Use @ref cudev instead. @@ -54,9 +53,6 @@ namespace cv { namespace cuda { namespace device { - using cv::cuda::device::compat::double4; - using cv::cuda::device::compat::make_double4; - template struct TypeVec; struct __align__(8) uchar8 diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_init_and_final.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_init_and_final.h new file mode 100644 index 0000000000000000000000000000000000000000..20f82c9e7e4b6e47b178841f700e89046be0cdc5 --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_init_and_final.h @@ -0,0 +1,16 @@ +// +// Created by hf on 2025/6/5. +// + +#ifndef OPENCV_CUST_INIT_AND_FINAL_H +#define OPENCV_CUST_INIT_AND_FINAL_H + +#include "opencv2/core/cvdef.h" + + +namespace cust::mpp::ive{ + // 用来表示初始化工作,有没有完成 + CV_EXPORTS bool inited(); +} + +#endif // OPENCV_CUST_INIT_AND_FINAL_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_log.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_log.h new file mode 100644 index 0000000000000000000000000000000000000000..a6ddf0709bb549a5de6d08c524ca13e6158779b6 --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_log.h @@ -0,0 +1,39 @@ + +#ifndef INC_CUST_LOG_H +#define INC_CUST_LOG_H +#define SPDLOG_HEADER_ONLY +#include "spdlog/sinks/basic_file_sink.h" // 文件输出 +#include "spdlog/sinks/stdout_color_sinks.h" // 控制台输出 +#include "spdlog/spdlog.h" +#include "spdlog/stopwatch.h" +#include "opencv2/core/cvdef.h" +namespace cust { +// 创建csv格式的日志文件 +using t_logger = ::std::shared_ptr; +CV_EXPORTS t_logger csv_logger(); +} // namespace cust + +#define CUST_LOGGER_INFO(...) \ + SPDLOG_LOGGER_INFO(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); \ + //::spdlog::shutdown(); + +#define CUST_LOGGER_WARN(...) \ + SPDLOG_LOGGER_WARN(::cust::csv_logger(), __VA_ARGS__) +#define CUST_LOGGER_ERROR(...) \ + SPDLOG_LOGGER_ERROR(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); \ + +#define CUST_LOGGER_TRACE(...) \ + SPDLOG_LOGGER_TRACE(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#define CUST_LOGGER_DEBUG(...) \ + SPDLOG_LOGGER_DEBUG(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#define CUST_LOGGER_CRITICAL(...) \ + SPDLOG_LOGGER_CRITICAL(::cust::csv_logger(), __VA_ARGS__); \ + ::cust::csv_logger()->flush(); + +#endif // INC_3_日志的使用_CUST_LOG_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h new file mode 100644 index 0000000000000000000000000000000000000000..4ab95346c96925c82b73c3f277b1b30e3adfb349 --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_meta_data_of_mem_block.h @@ -0,0 +1,56 @@ +// +// Created by hf on 2025/6/5. +// + +#ifndef OPENCV_META_DATA_OF_MEM_BLOCK_H +#define OPENCV_META_DATA_OF_MEM_BLOCK_H + +#include + +#include "opencv2/core/cvdef.h" + + + +namespace cust { +namespace memory { +namespace mpp { +namespace mmz { + +// 这里存放的是MPP的MMZ内存块专用的元数据 +class meta_data_of_mem_block { +public: + //物理地址 + meta_data_of_mem_block(unsigned int len, const char *mmb = nullptr, + const char *zone = nullptr); + ~meta_data_of_mem_block(); + ::std::string txt; +public: + // 输出 + void *phys_addr; // 物理地址 + void *virt_addr; // 虚拟地址 + unsigned int len; // 字节数 +private: + // 输入 + const char *mmb; + const char *zone; + +private: + // 配置 + bool need_free = false; +}; + +} // namespace mmz +} // namespace mpp +} // namespace memory +// 这是一个集查询和设置为一体的enable控制函数 +// operation=0表示查询 +// operation=1表示设置enable为true +// operation=-1表示设置enable为false +// enable控制函数的存在意义是在运行期间,不用重启程序就能够禁用和启用优化。 +// 这样我们才可以编写一个程序:这个程序能够对比优化前后的效果。 +CV_EXPORTS bool enable(int operation=0); +} // namespace cust + + + +#endif // OPENCV_META_DATA_OF_MEM_BLOCK_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_mpp_allocator.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_mpp_allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..4ec9bd7dc025ad6a87599ad4786a10f241008e0c --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cust_mpp_allocator.h @@ -0,0 +1,58 @@ +// +// Created by hf on 2025/6/5. +// + +#ifndef OPENCV_CUST_MPP_ALLOCATOR_H +#define OPENCV_CUST_MPP_ALLOCATOR_H +// #include "opencv2/core/cust_meta_data_of_mem_block.h" +// #include "opencv2/core/cust_log.h" +// #include + +namespace cust { +namespace mpp { +namespace mmz { +using namespace cv; +class allocator_for_mmz : public ::cv::MatAllocator { +private: + // 以下这两个方法负责内存的申请和释放 + static uchar* alloc(size_t total); + static void free(uchar* pData); +public: + //以下是构造函数,负责把此前的分配器保存起来 + allocator_for_mmz(); + // 重写的第一个API函数:用来向上层分配内存空间 + UMatData *allocate(int dims, const int *sizes, int type, void *data0, + size_t *step, AccessFlag flags, + UMatUsageFlags usageFlags) const override; + // 重写的第二个API函数:用来满足上层的内存释放请求 + void deallocate(UMatData *u) const override; + // 这是三个参数的内存申请函数,到底是干啥的不知道 + bool allocate(UMatData *data, AccessFlag accessflags, + UMatUsageFlags usageFlags) const override; + +private: + // 以下这个用来保存原来的分配器 + MatAllocator *std_allocator; +}; + +// 这个用来初始化和终结化 +// 初始化的目的就是使能 +// 终结化的目的就是禁用 +class init_and_final { +private: + allocator_for_mmz custom_allocator; +public: + init_and_final(); + ~init_and_final(); +}; + + +} // namespace mmz +} // namespace mpp +} // namespace cust + +namespace cv{ + CV_EXPORTS std::shared_ptr cust_mpp_get_meta_data(InputArray data); +} + +#endif // OPENCV_CUST_MPP_ALLOCATOR_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_dispatch.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_dispatch.h index 8b39dd549c7ac10ceabdf4762e515313adf6ff49..607f2866158427def3e9e4c62723764e25e33220 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_dispatch.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_dispatch.h @@ -72,7 +72,7 @@ # define CV_AVX 1 #endif #ifdef CV_CPU_COMPILE_FP16 -# if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) +# if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) # include # else # include @@ -137,7 +137,7 @@ # define CV_FMA3 1 #endif -#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) +#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) # include # include # define CV_NEON 1 @@ -230,17 +230,13 @@ struct VZeroUpperGuard { # define CV_MMX 1 # define CV_SSE 1 # define CV_SSE2 1 -#elif defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) +#elif defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER)) # include # include # define CV_NEON 1 #elif defined(__ARM_NEON) # include # define CV_NEON 1 -#ifdef __ARM_FEATURE_SVE -# include -# define CV_SVE 1 -#endif #elif defined(__VSX__) && defined(__PPC64__) && defined(__LITTLE_ENDIAN__) # include # undef vector @@ -366,10 +362,6 @@ struct VZeroUpperGuard { # define CV_NEON 0 #endif -#ifndef CV_SVE -# define CV_SVE 0 -#endif - #ifndef CV_RVV071 # define CV_RVV071 0 #endif diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_helper.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_helper.h index d521b066d4beff16484c679d2ed81c3603baf20f..04b00d20244394721b5d76167dd0c8e27f102574 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_helper.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cv_cpu_helper.h @@ -399,27 +399,6 @@ #endif #define __CV_CPU_DISPATCH_CHAIN_AVX512_ICL(fn, args, mode, ...) CV_CPU_CALL_AVX512_ICL(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__)) -#if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_SVE -# define CV_TRY_SVE 1 -# define CV_CPU_FORCE_SVE 1 -# define CV_CPU_HAS_SUPPORT_SVE 1 -# define CV_CPU_CALL_SVE(fn, args) return (cpu_baseline::fn args) -# define CV_CPU_CALL_SVE_(fn, args) return (opt_SVE::fn args) -#elif !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_DISPATCH_COMPILE_SVE -# define CV_TRY_SVE 1 -# define CV_CPU_FORCE_SVE 0 -# define CV_CPU_HAS_SUPPORT_SVE (cv::checkHardwareSupport(CV_CPU_SVE)) -# define CV_CPU_CALL_SVE(fn, args) if (CV_CPU_HAS_SUPPORT_SVE) return (opt_SVE::fn args) -# define CV_CPU_CALL_SVE_(fn, args) if (CV_CPU_HAS_SUPPORT_SVE) return (opt_SVE::fn args) -#else -# define CV_TRY_SVE 0 -# define CV_CPU_FORCE_SVE 0 -# define CV_CPU_HAS_SUPPORT_SVE 0 -# define CV_CPU_CALL_SVE(fn, args) -# define CV_CPU_CALL_SVE_(fn, args) -#endif -#define __CV_CPU_DISPATCH_CHAIN_SVE(fn, args, mode, ...) CV_CPU_CALL_SVE(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__)) - #if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_NEON # define CV_TRY_NEON 1 # define CV_CPU_FORCE_NEON 1 diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cvdef.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cvdef.h index eda0d3edbc90af9f626bc4005d5c4c3ef613903a..0e6d6ff49bc7830015071cd098790d09abeb6ea1 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cvdef.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/cvdef.h @@ -279,7 +279,6 @@ namespace cv { #define CV_CPU_NEON_DOTPROD 101 #define CV_CPU_NEON_FP16 102 #define CV_CPU_NEON_BF16 103 -#define CV_CPU_SVE 104 #define CV_CPU_MSA 150 @@ -342,7 +341,6 @@ enum CpuFeatures { CPU_NEON_DOTPROD = 101, CPU_NEON_FP16 = 102, CPU_NEON_BF16 = 103, - CPU_SVE = 104, CPU_MSA = 150, @@ -370,7 +368,7 @@ enum CpuFeatures { #include "cv_cpu_dispatch.h" -#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) +#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64)) // int*, int64* should be propertly aligned pointers on ARMv7 #define CV_STRONG_ALIGNMENT 1 #endif @@ -699,7 +697,7 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType) #ifdef CV_XADD // allow to use user-defined macro #elif defined __GNUC__ || defined __clang__ -# if defined __clang__ && __clang_major__ >= 3 && !defined __EMSCRIPTEN__ && !defined __INTEL_COMPILER +# if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) && !defined __INTEL_COMPILER # ifdef __ATOMIC_ACQ_REL # define CV_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) # else diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/fast_math.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/fast_math.hpp index 370f5b439b9876ef39b07eb46538cdfe1a566d3f..a28c3fbedfe690f6e8da6c0807aed18302c9b68b 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/fast_math.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/fast_math.hpp @@ -201,10 +201,6 @@ cvRound( double value ) { #if defined CV_INLINE_ROUND_DBL CV_INLINE_ROUND_DBL(value); -#elif defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) - float64x1_t v = vdup_n_f64(value); - int64x1_t r = vcvtn_s64_f64(v); - return static_cast(vget_lane_s64(r, 0)); #elif ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __SSE2__)) && !defined(__CUDACC__) __m128d t = _mm_set_sd( value ); return _mm_cvtsd_si32(t); @@ -307,7 +303,7 @@ CV_INLINE int cvIsInf( double value ) { #if defined CV_INLINE_ISINF_DBL CV_INLINE_ISINF_DBL(value); -#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__PPC64__) || defined(__loongarch64) +#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__PPC64__) || defined(__loongarch64) Cv64suf ieee754; ieee754.f = value; return (ieee754.u & 0x7fffffffffffffff) == @@ -327,10 +323,6 @@ CV_INLINE int cvRound(float value) { #if defined CV_INLINE_ROUND_FLT CV_INLINE_ROUND_FLT(value); -#elif defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) - float32x2_t v = vdup_n_f32(value); - int32x2_t r = vcvtn_s32_f32(v); - return vget_lane_s32(r, 0); #elif ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __SSE2__)) && !defined(__CUDACC__) __m128 t = _mm_set_ss( value ); return _mm_cvtss_si32(t); diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_cpp.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_cpp.hpp index 756602c7106f3561a21bdd3dc5415d48c74be253..3e5d484145aae842d1c02826f87fc840155d420d 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_cpp.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_cpp.hpp @@ -81,26 +81,9 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN "Universal intrinsics" is a types and functions set intended to simplify vectorization of code on different platforms. Currently a few different SIMD extensions on different architectures are supported. - -OpenCV Universal Intrinsics support the following instruction sets: - -- *128 bit* registers of various types support is implemented for a wide range of architectures including - - x86(SSE/SSE2/SSE4.2), - - ARM(NEON): 64-bit float (64F) requires AArch64, - - PowerPC(VSX), - - MIPS(MSA), - - LoongArch(LSX), - - RISC-V(RVV 0.7.1): Fixed-length implementation, - - WASM: 64-bit float (64F) is not supported, -- *256 bit* registers are supported on - - x86(AVX2), - - LoongArch (LASX), -- *512 bit* registers are supported on - - x86(AVX512), -- *Vector Length Agnostic (VLA)* registers are supported on - - RISC-V(RVV 1.0) - - ARM(SVE/SVE2): Powered by Arm KleidiCV integration (OpenCV 4.11+), - +128 bit registers of various types support is implemented for a wide range of architectures +including x86(__SSE/SSE2/SSE4.2__), ARM(__NEON__), PowerPC(__VSX__), MIPS(__MSA__). +256 bit long registers are supported on x86(__AVX2__) and 512 bit long registers are supported on x86(__AVX512__). In case when there is no SIMD extension available during compilation, fallback C++ implementation of intrinsics will be chosen and code will work as expected although it could be slower. @@ -242,30 +225,32 @@ These operations allow to reorder or recombine elements in one or multiple vecto Element-wise binary and unary operations. - Arithmetics: -@ref v_add, -@ref v_sub, -@ref v_mul, -@ref v_div, +@ref v_add(const v_reg &a, const v_reg &b) "+", +@ref v_sub(const v_reg &a, const v_reg &b) "-", +@ref v_mul(const v_reg &a, const v_reg &b) "*", +@ref v_div(const v_reg &a, const v_reg &b) "/", @ref v_mul_expand - Non-saturating arithmetics: @ref v_add_wrap, @ref v_sub_wrap - Bitwise shifts: +@ref v_shl(const v_reg &a, int s) "<<", +@ref v_shr(const v_reg &a, int s) ">>", @ref v_shl, @ref v_shr - Bitwise logic: -@ref v_and, -@ref v_or, -@ref v_xor, -@ref v_not +@ref v_and(const v_reg &a, const v_reg &b) "&", +@ref v_or(const v_reg &a, const v_reg &b) "|", +@ref v_xor(const v_reg &a, const v_reg &b) "^", +@ref v_not(const v_reg &a) "~" - Comparison: -@ref v_gt, -@ref v_ge, -@ref v_lt, -@ref v_le, -@ref v_eq, -@ref v_ne +@ref v_gt(const v_reg &a, const v_reg &b) ">", +@ref v_ge(const v_reg &a, const v_reg &b) ">=", +@ref v_lt(const v_reg &a, const v_reg &b) "<", +@ref v_le(const v_reg &a, const v_reg &b) "<=", +@ref v_eq(const v_reg &a, const v_reg &b) "==", +@ref v_ne(const v_reg &a, const v_reg &b) "!=" - min/max: @ref v_min, @ref v_max diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h deleted file mode 100644 index 764c245df9a994f72419123a5a863efc70ba6649..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_legacy_ops.h +++ /dev/null @@ -1,111 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html - -// This file has been created for compatibility with older versions of Universal Intrinscs -// Binary operators for vector types has been removed since version 4.11 -// Include this file manually after OpenCV headers if you need these operators - -#ifndef OPENCV_HAL_INTRIN_LEGACY_OPS_HPP -#define OPENCV_HAL_INTRIN_LEGACY_OPS_HPP - -#ifdef __OPENCV_BUILD -#error "Universal Intrinsics operators are deprecated and should not be used in OpenCV library" -#endif - -#ifdef __riscv -#warning "Operators might conflict with built-in functions on RISC-V platform" -#endif - -#if defined(CV_VERSION) && CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR < 9 -#warning "Older versions of OpenCV (<4.9) already have Universal Intrinscs operators" -#endif - - -namespace cv { namespace hal { - -#define BIN_OP(OP, FUN) \ -template R operator OP (const R & lhs, const R & rhs) { return FUN(lhs, rhs); } - -#define BIN_A_OP(OP, FUN) \ -template R & operator OP (R & res, const R & val) { res = FUN(res, val); return res; } - -#define UN_OP(OP, FUN) \ -template R operator OP (const R & val) { return FUN(val); } - -BIN_OP(+, v_add) -BIN_OP(-, v_sub) -BIN_OP(*, v_mul) -BIN_OP(/, v_div) -BIN_OP(&, v_and) -BIN_OP(|, v_or) -BIN_OP(^, v_xor) - -BIN_OP(==, v_eq) -BIN_OP(!=, v_ne) -BIN_OP(<, v_lt) -BIN_OP(>, v_gt) -BIN_OP(<=, v_le) -BIN_OP(>=, v_ge) - -BIN_A_OP(+=, v_add) -BIN_A_OP(-=, v_sub) -BIN_A_OP(*=, v_mul) -BIN_A_OP(/=, v_div) -BIN_A_OP(&=, v_and) -BIN_A_OP(|=, v_or) -BIN_A_OP(^=, v_xor) - -UN_OP(~, v_not) - -// TODO: shift operators? - -}} // cv::hal:: - -//============================================================================== - -#ifdef OPENCV_ENABLE_INLINE_INTRIN_OPERATOR_TEST - -namespace cv { namespace hal { - -inline static void opencv_operator_compile_test() -{ - using namespace cv; - v_float32 a, b, c; - uint8_t shift = 1; - a = b + c; - a = b - c; - a = b * c; - a = b / c; - a = b & c; - a = b | c; - a = b ^ c; - // a = b >> shift; - // a = b << shift; - - a = (b == c); - a = (b != c); - a = (b < c);}} - a = (b > c); - a = (b <= c); - a = (b >= c); - - a += b; - a -= b; - a *= b; - a /= b; - a &= b; - a |= b; - a ^= b; - // a <<= shift; - // a >>= shift; - - a = ~b; -} - -}} // cv::hal:: - -#endif - - -#endif // OPENCV_HAL_INTRIN_LEGACY_OPS_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_neon.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_neon.hpp index 074e96da8a5719065302e67c0639129360050969..64fb7d73bc66a930cdc47e56f0aa7493da14de8a 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_neon.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_neon.hpp @@ -56,7 +56,7 @@ namespace cv CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN #define CV_SIMD128 1 -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) #define CV_SIMD128_64F 1 #else #define CV_SIMD128_64F 0 @@ -72,7 +72,7 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN // // [1] https://developer.arm.com/documentation/101028/0012/13--Advanced-SIMD--Neon--intrinsics // [2] https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros -#if defined(__ARM_64BIT_STATE) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__ARM_64BIT_STATE) || defined(_M_ARM64) #define CV_NEON_AARCH64 1 #else #define CV_NEON_AARCH64 0 @@ -888,10 +888,9 @@ inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b) { - int16x8_t p0 = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val)); - int16x8_t p1 = vmull_s8(vget_high_s8(a.val), vget_high_s8(b.val)); - int32x4_t s0 = vaddl_s16(vget_low_s16(p0), vget_low_s16(p1)); - return v_int32x4(vaddq_s32(s0, vaddl_s16(vget_high_s16(p0), vget_high_s16(p1)))); + int16x8_t prod = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val)); + prod = vmlal_s8(prod, vget_high_s8(a.val), vget_high_s8(b.val)); + return v_int32x4(vaddl_s16(vget_low_s16(prod), vget_high_s16(prod))); } inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c) { @@ -1081,7 +1080,7 @@ OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int16x8, vreinterpretq_s16_u16, s16, u16) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32) OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32) -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) static inline uint64x2_t vmvnq_u64(uint64x2_t a) { uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF)); @@ -1823,7 +1822,7 @@ inline v_int32x4 v_load_expand_q(const schar* ptr) return v_int32x4(vmovl_s16(v1)); } -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(__aarch64__) || defined(_M_ARM64) #define OPENCV_HAL_IMPL_NEON_UNPACKS(_Tpvec, suffix) \ inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \ { \ diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp index 67c9d12741be787d22987a38d1a93e0a0dd75cb2..b6ce2d7f47cc9aa982fb1392401eb041e5e37602 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_rvv_scalable.hpp @@ -8,7 +8,6 @@ #ifndef OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP #define OPENCV_HAL_INTRIN_RVV_SCALABLE_HPP -#include #include #if defined(__GNUC__) && !defined(__clang__) @@ -63,9 +62,8 @@ struct VTraits \ { \ static inline int vlanes() { return __riscv_vsetvlmax_##SUF(); } \ using lane_type = TYP; \ - static const int max_nlanes = CV_RVV_MAX_VLEN/SZ*2; \ + static const int max_nlanes = CV_RVV_MAX_VLEN/SZ; \ }; -// `max_nlanes` is multiplied by 2 because of using LMUL=2 (m2) OPENCV_HAL_IMPL_RVV_TRAITS(vint8m1_t, int8_t, e8m1, 8) OPENCV_HAL_IMPL_RVV_TRAITS(vint8m2_t, int8_t, e8m2, 8) @@ -509,28 +507,6 @@ inline v_float64 v_lut(const double* tab, const v_int32& vidx) \ #endif -// Strangely, __riscv_vluxseg2ei32 is slower (tested on Muse-Pi and CanMV K230) -#define OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(_Tpvec, _Tp, suffix) \ -inline void v_lut_deinterleave(const _Tp* tab, const v_int32& vidx, _Tpvec& vx, _Tpvec& vy) \ -{ \ - v_uint32 vidx_ = __riscv_vmul(__riscv_vreinterpret_u32m2(vidx), sizeof(_Tp), VTraits::vlanes()); \ - vx = __riscv_vluxei32(tab, vidx_, VTraits<_Tpvec>::vlanes()); \ - vy = __riscv_vluxei32(tab, __riscv_vadd(vidx_, sizeof(_Tp), VTraits::vlanes()), VTraits<_Tpvec>::vlanes()); \ -} -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_float32, float, f32) -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_int32, int, i32) -OPENCV_HAL_IMPL_RVV_LUT_DEINTERLEAVE(v_uint32, unsigned, u32) - -#if CV_SIMD_SCALABLE_64F -inline void v_lut_deinterleave(const double* tab, const v_int32& vidx, v_float64& vx, v_float64& vy) \ -{ \ - vuint32m1_t vidx_ = __riscv_vmul(__riscv_vlmul_trunc_u32m1(__riscv_vreinterpret_u32m2(vidx)), sizeof(double), VTraits::vlanes()); \ - vx = __riscv_vluxei32(tab, vidx_, VTraits::vlanes()); \ - vy = __riscv_vluxei32(tab, __riscv_vadd(vidx_, sizeof(double), VTraits::vlanes()), VTraits::vlanes()); \ -} -#endif - - inline v_uint8 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); } inline v_uint8 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); } inline v_uint8 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); } @@ -1614,31 +1590,23 @@ OPENCV_HAL_IMPL_RVV_INTERLEAVED(int64, int64, i64, 64, 32, VTraits::vla OPENCV_HAL_IMPL_RVV_INTERLEAVED(float64, double, f64, 64, 32, VTraits::vlanes()) #endif -static std::array idx_interleave_pairs = { \ +static uint64_t idx_interleave_pairs[] = { \ 0x0705060403010200, 0x0f0d0e0c0b090a08, 0x1715161413111210, 0x1f1d1e1c1b191a18, \ 0x2725262423212220, 0x2f2d2e2c2b292a28, 0x3735363433313230, 0x3f3d3e3c3b393a38, \ 0x4745464443414240, 0x4f4d4e4c4b494a48, 0x5755565453515250, 0x5f5d5e5c5b595a58, \ - 0x6765666463616260, 0x6f6d6e6c6b696a68, 0x7775767473717270, 0x7f7d7e7c7b797a78, \ - 0x8785868483818280, 0x8f8d8e8c8b898a88, 0x9795969493919290, 0x9f9d9e9c9b999a98, \ - 0xa7a5a6a4a3a1a2a0, 0xafadaeacaba9aaa8, 0xb7b5b6b4b3b1b2b0, 0xbfbdbebcbbb9bab8, \ - 0xc7c5c6c4c3c1c2c0, 0xcfcdcecccbc9cac8, 0xd7d5d6d4d3d1d2d0, 0xdfdddedcdbd9dad8, \ - 0xe7e5e6e4e3e1e2e0, 0xefedeeecebe9eae8, 0xf7f5f6f4f3f1f2f0, 0xfffdfefcfbf9faf8}; + 0x6765666463616260, 0x6f6d6e6c6b696a68, 0x7775767473717270, 0x7f7d7e7c7b797a78}; -static std::array idx_interleave_quads = { \ +static uint64_t idx_interleave_quads[] = { \ 0x0703060205010400, 0x0f0b0e0a0d090c08, 0x1713161215111410, 0x1f1b1e1a1d191c18, \ 0x2723262225212420, 0x2f2b2e2a2d292c28, 0x3733363235313430, 0x3f3b3e3a3d393c38, \ 0x4743464245414440, 0x4f4b4e4a4d494c48, 0x5753565255515450, 0x5f5b5e5a5d595c58, \ - 0x6763666265616460, 0x6f6b6e6a6d696c68, 0x7773767275717470, 0x7f7b7e7a7d797c78, \ - 0x8783868285818480, 0x8f8b8e8a8d898c88, 0x9793969295919490, 0x9f9b9e9a9d999c98, \ - 0xa7a3a6a2a5a1a4a0, 0xafabaeaaada9aca8, 0xb7b3b6b2b5b1b4b0, 0xbfbbbebabdb9bcb8, \ - 0xc7c3c6c2c5c1c4c0, 0xcfcbcecacdc9ccc8, 0xd7d3d6d2d5d1d4d0, 0xdfdbdedaddd9dcd8, \ - 0xe7e3e6e2e5e1e4e0, 0xefebeeeaede9ece8, 0xf7f3f6f2f5f1f4f0, 0xfffbfefafdf9fcf8}; + 0x6763666265616460, 0x6f6b6e6a6d696c68, 0x7773767275717470, 0x7f7b7e7a7d797c78}; #define OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(_Tpvec, func) \ inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ vuint8m2_t vidx = __riscv_vundefined_u8m2();\ - vidx = __riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func.data(), idx_interleave_##func.size())); \ + vidx = __riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func, 16)); \ return __riscv_vrgather(vec, vidx, VTraits::vlanes()); \ } OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_uint8, pairs) @@ -1650,7 +1618,7 @@ OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_int8, quads) inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ vuint##width##m2_t vidx = __riscv_vundefined_u##width##m2();\ - vidx = __riscv_vget_u##width##m2(vzext_vfx(__riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func.data(), idx_interleave_##func.size())), VTraits::vlanes()), 0); \ + vidx = __riscv_vget_u##width##m2(vzext_vfx(__riscv_vreinterpret_u8m2(__riscv_vle64_v_u64m2(idx_interleave_##func, 16)), VTraits::vlanes()), 0); \ return __riscv_vrgather(vec, vidx, VTraits<_Tpvec>::vlanes()); \ } @@ -1722,19 +1690,20 @@ inline v_uint64 v_popcount(const v_uint64& a) inline v_uint8 v_popcount(const v_int8& a) { - return v_popcount(__riscv_vreinterpret_u8m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint16 v_popcount(const v_int16& a) { - return v_popcount(__riscv_vreinterpret_u16m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint32 v_popcount(const v_int32& a) { - return v_popcount(__riscv_vreinterpret_u32m2(a));\ + return v_popcount(v_abs(a));\ } inline v_uint64 v_popcount(const v_int64& a) { - return v_popcount(__riscv_vreinterpret_u64m2(a)); + // max(0 - a) is used, since v_abs does not support 64-bit integers. + return v_popcount(v_reinterpret_as_u64(__riscv_vmax(a, v_sub(v_setzero_s64(), a), VTraits::vlanes()))); } @@ -1828,14 +1797,14 @@ inline void v_pack_store(hfloat* ptr, const v_float32& v) #else inline v_float32 v_load_expand(const hfloat* ptr) { - float buf[VTraits::max_nlanes]; + float buf[32]; for( int i = 0; i < VTraits::vlanes(); i++ ) buf[i] = (float)ptr[i]; return v_load(buf); } inline void v_pack_store(hfloat* ptr, const v_float32& v) { - float buf[VTraits::max_nlanes]; + float buf[32]; v_store(buf, v); for( int i = 0; i < VTraits::vlanes(); i++ ) ptr[i] = hfloat(buf[i]); } @@ -2130,17 +2099,7 @@ inline v_int64 v_dotprod_expand_fast(const v_int16& a, const v_int16& b, const v // 32 >> 64f #if CV_SIMD_SCALABLE_64F inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b) -{ - vfloat64m1_t zero = __riscv_vfmv_v_f_f64m1(0, VTraits::vlanes()); - auto prod_i64 = __riscv_vwmul(a, b, VTraits::vlanes()); - // Convert to f64 before reduction to avoid overflow: #27003 - auto prod_f64 = __riscv_vfcvt_f(prod_i64, VTraits::vlanes()); - return __riscv_vset( // Needs v_float64 (vfloat64m2_t) here. - v_setall_f64(0.0f), // zero_f64m2 - 0, - __riscv_vfredusum_tu(zero, prod_f64, zero, VTraits::vlanes()) - ); -} +{ return v_cvt_f64(v_dotprod_fast(a, b)); } inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b, const v_float64& c) { return v_add(v_dotprod_expand_fast(a, b) , c); } #endif diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_vsx.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_vsx.hpp index 0a0915a22fc4ccdc80e5be5e9d8c33f01f468fa8..2157e1e87063e0e3b7a38d194130acf222360fb9 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_vsx.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/hal/intrin_vsx.hpp @@ -262,7 +262,7 @@ OPENCV_HAL_IMPL_VSX_EXTRACT_N(v_float64x2, double) inline _Tpvec v_setzero_##suffix() { return _Tpvec(vec_splats((_Tp)0)); } \ inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(vec_splats((_Tp)v));} \ template <> inline _Tpvec v_setzero_() { return v_setzero_##suffix(); } \ -template <> inline _Tpvec v_setall_(_Tp v) { return v_setall_##suffix(v); } \ +template <> inline _Tpvec v_setall_(_Tp v) { return v_setall_##suffix(_Tp v); } \ template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0 &a) \ { return _Tpvec((cast)a.val); } @@ -650,11 +650,11 @@ OPENCV_HAL_IMPL_VSX_SELECT(v_float64x2, vec_bdword2_c) #define OPENCV_HAL_IMPL_VSX_INT_CMP_OP(_Tpvec) \ inline _Tpvec v_eq(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpeq(a.val, b.val)); } \ -inline _Tpvec v_ne(const _Tpvec& a, const _Tpvec& b) \ +inline _Tpvec V_ne(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpne(a.val, b.val)); } \ inline _Tpvec v_lt(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmplt(a.val, b.val)); } \ -inline _Tpvec v_gt(const _Tpvec& a, const _Tpvec& b) \ +inline _Tpvec V_gt(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmpgt(a.val, b.val)); } \ inline _Tpvec v_le(const _Tpvec& a, const _Tpvec& b) \ { return _Tpvec(vec_cmple(a.val, b.val)); } \ @@ -1507,7 +1507,7 @@ inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b, cons inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b) { return v_dotprod(a, b); } inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c) -{ return v_add(v_int32x4(vec_msum(a.val, b.val, vec_int4_z)), c); } +{ return v_int32x4(vec_msum(a.val, b.val, vec_int4_z)) + c; } // 32 >> 64 inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b) { return v_dotprod(a, b); } @@ -1518,7 +1518,7 @@ inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_ inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b) { return v_dotprod_expand(a, b); } inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c) -{ return v_add(v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)), c); } +{ return v_uint32x4(vec_msum(a.val, b.val, vec_uint4_z)) + c; } inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b) { diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.hpp index 78f7487e51201becaf3ac8d40b5781917bca41a7..2282e12aeef5204d9a2537aa051967cbc1648be9 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.hpp @@ -185,8 +185,7 @@ public: #if OPENCV_ABI_COMPATIBILITY < 500 STD_ARRAY =14 << KIND_SHIFT, //!< removed: https://github.com/opencv/opencv/issues/18897 #endif - STD_ARRAY_MAT =15 << KIND_SHIFT, - CUDA_GPU_MATND =16 << KIND_SHIFT + STD_ARRAY_MAT =15 << KIND_SHIFT }; _InputArray(); @@ -205,7 +204,6 @@ public: _InputArray(const double& val); _InputArray(const cuda::GpuMat& d_mat); _InputArray(const std::vector& d_mat_array); - _InputArray(const cuda::GpuMatND& d_mat); _InputArray(const ogl::Buffer& buf); _InputArray(const cuda::HostMem& cuda_mem); template _InputArray(const cudev::GpuMat_<_Tp>& m); @@ -225,7 +223,6 @@ public: void getUMatVector(std::vector& umv) const; void getGpuMatVector(std::vector& gpumv) const; cuda::GpuMat getGpuMat() const; - cuda::GpuMatND getGpuMatND() const; ogl::Buffer getOGlBuffer() const; int getFlags() const; @@ -246,7 +243,6 @@ public: bool isContinuous(int i=-1) const; bool isSubmatrix(int i=-1) const; bool empty() const; - bool empty(int i) const; void copyTo(const _OutputArray& arr) const; void copyTo(const _OutputArray& arr, const _InputArray & mask) const; size_t offset(int i=-1) const; @@ -259,7 +255,6 @@ public: bool isVector() const; bool isGpuMat() const; bool isGpuMatVector() const; - bool isGpuMatND() const; ~_InputArray(); protected: @@ -323,7 +318,6 @@ public: _OutputArray(std::vector& vec); _OutputArray(cuda::GpuMat& d_mat); _OutputArray(std::vector& d_mat); - _OutputArray(cuda::GpuMatND& d_mat); _OutputArray(ogl::Buffer& buf); _OutputArray(cuda::HostMem& cuda_mem); template _OutputArray(cudev::GpuMat_<_Tp>& m); @@ -342,7 +336,6 @@ public: _OutputArray(const std::vector& vec); _OutputArray(const cuda::GpuMat& d_mat); _OutputArray(const std::vector& d_mat); - _OutputArray(const cuda::GpuMatND& d_mat); _OutputArray(const ogl::Buffer& buf); _OutputArray(const cuda::HostMem& cuda_mem); template _OutputArray(const cudev::GpuMat_<_Tp>& m); @@ -370,7 +363,6 @@ public: UMat& getUMatRef(int i=-1) const; cuda::GpuMat& getGpuMatRef() const; std::vector& getGpuMatVecRef() const; - cuda::GpuMatND& getGpuMatNDRef() const; ogl::Buffer& getOGlBufferRef() const; cuda::HostMem& getHostMemRef() const; void create(Size sz, int type, int i=-1, bool allowTransposed=false, _OutputArray::DepthMask fixedDepthMask=static_cast<_OutputArray::DepthMask>(0)) const; @@ -380,7 +372,6 @@ public: void release() const; void clear() const; void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const; - Mat reinterpret( int type ) const; void assign(const UMat& u) const; void assign(const Mat& m) const; @@ -401,7 +392,6 @@ public: _InputOutputArray(Mat& m); _InputOutputArray(std::vector& vec); _InputOutputArray(cuda::GpuMat& d_mat); - _InputOutputArray(cuda::GpuMatND& d_mat); _InputOutputArray(ogl::Buffer& buf); _InputOutputArray(cuda::HostMem& cuda_mem); template _InputOutputArray(cudev::GpuMat_<_Tp>& m); @@ -419,7 +409,6 @@ public: _InputOutputArray(const std::vector& vec); _InputOutputArray(const cuda::GpuMat& d_mat); _InputOutputArray(const std::vector& d_mat); - _InputOutputArray(const cuda::GpuMatND& d_mat); _InputOutputArray(const ogl::Buffer& buf); _InputOutputArray(const cuda::HostMem& cuda_mem); template _InputOutputArray(const cudev::GpuMat_<_Tp>& m); @@ -1247,13 +1236,8 @@ public: When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, the newly allocated matrix is initialized with all zeros before copying the data. - - If (re)allocation of destination memory is not necessary (e.g. updating ROI), use copyAt() . - @param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated. - - @sa copyAt */ void copyTo( OutputArray m ) const; @@ -1265,30 +1249,6 @@ public: */ void copyTo( OutputArray m, InputArray mask ) const; - /** @brief Overwrites the existing matrix - - This method writes existing matrix data, just like copyTo(). - But if it does not have a proper size or type before the operation, an exception is thrown. - This function is helpful to update ROI in an existing matrix. - - If (re)allocation of destination memory is necessary, use copyTo() . - - @param m Destination matrix. - If it does not have a proper size or type before the operation, an exception is thrown. - - @sa copyTo - - */ - void copyAt( OutputArray m ) const; - - /** @overload - @param m Destination matrix. - If it does not have a proper size or type before the operation, an exception is thrown. - @param mask Operation mask of the same size as \*this. Its non-zero elements indicate which matrix - elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels. - */ - void copyAt( OutputArray m, InputArray mask ) const; - /** @brief Converts an array to another data type with optional scaling. The method converts source pixel values to the target data type. saturate_cast\<\> is applied at @@ -1366,28 +1326,19 @@ public: /** @overload * @param cn New number of channels. If the parameter is 0, the number of channels remains the same. - * @param newndims New number of dimensions. - * @param newsz Array with new matrix size by all dimensions. If some sizes are zero, + * @param newndims New number of dimentions. + * @param newsz Array with new matrix size by all dimentions. If some sizes are zero, * the original sizes in those dimensions are presumed. */ Mat reshape(int cn, int newndims, const int* newsz) const; /** @overload * @param cn New number of channels. If the parameter is 0, the number of channels remains the same. - * @param newshape Vector with new matrix size by all dimensions. If some sizes are zero, + * @param newshape Vector with new matrix size by all dimentions. If some sizes are zero, * the original sizes in those dimensions are presumed. */ Mat reshape(int cn, const std::vector& newshape) const; - /** @brief Reset the type of matrix. - - The methods reset the data type of matrix. If the new type and the old type of the matrix - have the same element size, the current buffer can be reused. The method needs to consider whether the - current mat is a submatrix or has any references. - @param type New data type. - */ - Mat reinterpret( int type ) const; - /** @brief Transposes a matrix. The method performs matrix transposition by means of matrix expressions. It does not perform the @@ -2521,8 +2472,8 @@ public: UMat(const UMat& m, const Range* ranges); UMat(const UMat& m, const std::vector& ranges); - //! builds matrix from std::vector. The data is always copied. The copyData - //! parameter is deprecated and will be removed in OpenCV 5.0. + // FIXIT copyData=false is not implemented, drop this in favor of cv::Mat (OpenCV 5.0) + //! builds matrix from std::vector with or without copying the data template explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); //! destructor - calls release() @@ -3605,7 +3556,7 @@ public: /** @brief Matrix expression representation @anchor MatrixExpressions This is a list of implemented matrix operations that can be combined in arbitrary complex -expressions (here A, B stand for matrices ( cv::Mat ), s for a cv::Scalar, alpha for a +expressions (here A, B stand for matrices ( Mat ), s for a scalar ( Scalar ), alpha for a real-valued scalar ( double )): - Addition, subtraction, negation: `A+B`, `A-B`, `A+s`, `A-s`, `s+A`, `s-A`, `-A` - Scaling: `A*alpha` @@ -3620,13 +3571,13 @@ real-valued scalar ( double )): 0. - Bitwise logical operations: `A logicop B`, `A logicop s`, `s logicop A`, `~A`, where *logicop* is one of `&`, `|`, `^`. -- Element-wise minimum and maximum: cv::min(A, B), cv::min(A, alpha), cv::max(A, B), cv::max(A, alpha) -- Element-wise absolute value: cv::abs(A) +- Element-wise minimum and maximum: `min(A, B)`, `min(A, alpha)`, `max(A, B)`, `max(A, alpha)` +- Element-wise absolute value: `abs(A)` - Cross-product, dot-product: `A.cross(B)`, `A.dot(B)` -- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as cv::norm, - cv::mean, cv::sum, cv::countNonZero, cv::trace, cv::determinant, cv::repeat, and others. +- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as norm, + mean, sum, countNonZero, trace, determinant, repeat, and others. - Matrix initializers ( Mat::eye(), Mat::zeros(), Mat::ones() ), matrix comma-separated - initializers, matrix constructors and operators that extract sub-matrices (see cv::Mat description). + initializers, matrix constructors and operators that extract sub-matrices (see Mat description). - Mat_() constructors to cast the result to the proper type. @note Comma-separated initializers and probably some other operations may require additional explicit Mat() or Mat_() constructor calls to resolve a possible ambiguity. diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.inl.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.inl.hpp index f0340643517d6d3c31a6bf01d175072cbb3f4073..bd0ba637b523c7d92ded4b87811f6efa6f0413a2 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.inl.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/mat.inl.hpp @@ -107,10 +107,7 @@ inline _InputArray::_InputArray(const std::vector& vec) { init(+STD_VECTOR template inline _InputArray::_InputArray(const std::vector<_Tp>& vec) -{ - CV_CheckLE(vec.size(), static_cast(std::numeric_limits::max()), "Must not be larger than INT_MAX"); - init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); -} +{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); } template inline _InputArray::_InputArray(const std::array<_Tp, _Nm>& arr) @@ -151,10 +148,7 @@ inline _InputArray::_InputArray(const cuda::GpuMat& d_mat) { init(+CUDA_GPU_MAT + ACCESS_READ, &d_mat); } inline _InputArray::_InputArray(const std::vector& d_mat) -{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat);} - -inline _InputArray::_InputArray(const cuda::GpuMatND& d_mat) -{ init(+CUDA_GPU_MATND + ACCESS_READ, &d_mat); } +{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat);} inline _InputArray::_InputArray(const ogl::Buffer& buf) { init(+OPENGL_BUFFER + ACCESS_READ, &buf); } @@ -200,7 +194,6 @@ inline bool _InputArray::isVector() const { return kind() == _InputArray::STD_VE (kind() == _InputArray::MATX && (sz.width <= 1 || sz.height <= 1)); } inline bool _InputArray::isGpuMat() const { return kind() == _InputArray::CUDA_GPU_MAT; } inline bool _InputArray::isGpuMatVector() const { return kind() == _InputArray::STD_VECTOR_CUDA_GPU_MAT; } -inline bool _InputArray::isGpuMatND() const { return kind() == _InputArray::CUDA_GPU_MATND; } //////////////////////////////////////////////////////////////////////////////////////// @@ -279,10 +272,7 @@ inline _OutputArray::_OutputArray(cuda::GpuMat& d_mat) { init(+CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } inline _OutputArray::_OutputArray(std::vector& d_mat) -{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat);} - -inline _OutputArray::_OutputArray(cuda::GpuMatND& d_mat) -{ init(+CUDA_GPU_MATND + ACCESS_WRITE, &d_mat); } +{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat);} inline _OutputArray::_OutputArray(ogl::Buffer& buf) { init(+OPENGL_BUFFER + ACCESS_WRITE, &buf); } @@ -305,8 +295,6 @@ inline _OutputArray::_OutputArray(const std::vector& vec) inline _OutputArray::_OutputArray(const cuda::GpuMat& d_mat) { init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } -inline _OutputArray::_OutputArray(const cuda::GpuMatND& d_mat) -{ init(+FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MATND + ACCESS_WRITE, &d_mat); } inline _OutputArray::_OutputArray(const ogl::Buffer& buf) { init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_WRITE, &buf); } @@ -409,9 +397,6 @@ _InputOutputArray::_InputOutputArray(const _Tp* vec, int n) inline _InputOutputArray::_InputOutputArray(cuda::GpuMat& d_mat) { init(+CUDA_GPU_MAT + ACCESS_RW, &d_mat); } -inline _InputOutputArray::_InputOutputArray(cuda::GpuMatND& d_mat) -{ init(+CUDA_GPU_MATND + ACCESS_RW, &d_mat); } - inline _InputOutputArray::_InputOutputArray(ogl::Buffer& buf) { init(+OPENGL_BUFFER + ACCESS_RW, &buf); } @@ -439,9 +424,6 @@ inline _InputOutputArray::_InputOutputArray(const std::vector& d_m template<> inline _InputOutputArray::_InputOutputArray(std::vector& d_mat) { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat);} -inline _InputOutputArray::_InputOutputArray(const cuda::GpuMatND& d_mat) -{ init(+FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MATND + ACCESS_RW, &d_mat); } - inline _InputOutputArray::_InputOutputArray(const ogl::Buffer& buf) { init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_RW, &buf); } @@ -3042,12 +3024,6 @@ Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) return *this; } -template inline -MatExpr Mat_<_Tp>::zeros(int _ndims, const int* _sizes) -{ - return Mat::zeros(_ndims, _sizes, traits::Type<_Tp>::value); -} - template inline MatExpr Mat_<_Tp>::zeros(int rows, int cols) { @@ -3272,13 +3248,18 @@ const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) template inline UMat::UMat(const std::vector<_Tp>& vec, bool copyData) - : flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), - cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) +: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), +cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) { - CV_UNUSED(copyData); // parameter kept for backward compatibility if(vec.empty()) return; - Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this); + if( !copyData ) + { + // !!!TODO!!! + CV_Error(Error::StsNotImplemented, ""); + } + else + Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this); } inline diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/quaternion.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/quaternion.hpp index d8882f6a54e7679af456b8da5a76d75fe79c1f58..e39065020c5f1cf89ec1dba9c1a9973a94bd4b93 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/quaternion.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/quaternion.hpp @@ -57,7 +57,7 @@ class QuatEnum public: /** @brief Enum of Euler angles type. * - * Without considering the possibility of using two different conversions for the definition of the rotation axes , + * Without considering the possibility of using two different convertions for the definition of the rotation axes , * there exists twelve possible sequences of rotation axes, divided into two groups: * - Proper Euler angles (Z-X-Z, X-Y-X, Y-Z-Y, Z-Y-Z, X-Z-X, Y-X-Y) * - Tait–Bryan angles (X-Y-Z, Y-Z-X, Z-X-Y, X-Z-Y, Z-Y-X, Y-X-Z). @@ -273,7 +273,7 @@ public: * where \f$ q_{X, \theta_1} \f$ is created from @ref createFromXRot, \f$ q_{Y, \theta_2} \f$ is created from @ref createFromYRot, * \f$ q_{Z, \theta_3} \f$ is created from @ref createFromZRot. * @param angles the Euler angles in a vector of length 3 - * @param eulerAnglesType the conversion Euler angles type + * @param eulerAnglesType the convertion Euler angles type */ static Quat<_Tp> createFromEulerAngles(const Vec<_Tp, 3> &angles, QuatEnum::EulerAnglesType eulerAnglesType); @@ -1610,7 +1610,7 @@ public: * EXT_ZXZ| \f$ \theta_1 = \arctan2(m_{31},m_{32}) \\\theta_2 = \arccos(m_{33}) \\\theta_3 = \arctan2(-m_{13},m_{23})\f$| \f$ \theta_1=0\\ \theta_2=0\\ \theta_3=\arctan2(m_{21},m_{22}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(m_{21},m_{11}) \f$ * EXT_ZYZ| \f$ \theta_1 = \arctan2(m_{32},-m_{31})\\\theta_2 = \arccos(m_{33}) \\\theta_3 = \arctan2(m_{23},m_{13}) \f$| \f$ \theta_1=0\\ \theta_2=0\\ \theta_3=\arctan2(m_{21},m_{11}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(m_{21},m_{11}) \f$ * - * @param eulerAnglesType the conversion Euler angles type + * @param eulerAnglesType the convertion Euler angles type */ Vec<_Tp, 3> toEulerAngles(QuatEnum::EulerAnglesType eulerAnglesType); diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/types.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/types.hpp index dab6a82dccd75466cbdeb647c333ca230bd1ff69..df4fd21885dedda99c5d0d1e059d34aa8e9d975e 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/types.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/types.hpp @@ -1931,7 +1931,7 @@ template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) { if (a.empty() || b.empty()) { - a = Rect_<_Tp>(); + a = Rect(); return a; } const Rect_<_Tp>& Rx_min = (a.x < b.x) ? a : b; @@ -1945,7 +1945,7 @@ Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) // Let us first deal with the following case. if ((Rx_min.x < 0 && Rx_min.x + Rx_min.width < Rx_max.x) || (Ry_min.y < 0 && Ry_min.y + Ry_min.height < Ry_max.y)) { - a = Rect_<_Tp>(); + a = Rect(); return a; } // We now know that either Rx_min.x >= 0, or @@ -1957,7 +1957,7 @@ Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) a.x = Rx_max.x; a.y = Ry_max.y; if (a.empty()) - a = Rect_<_Tp>(); + a = Rect(); return a; } diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/utils/logger.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/utils/logger.hpp index c58b0ccf6a5f93a12ead0ea9ca68dcd5f6cf6cfe..accb860ada8e3197f34e1226f1097784c8046ea2 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/utils/logger.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/utils/logger.hpp @@ -22,9 +22,9 @@ namespace logging { /** Set global logging level @return previous logging level */ -CV_EXPORTS_W LogLevel setLogLevel(LogLevel logLevel); +CV_EXPORTS LogLevel setLogLevel(LogLevel logLevel); /** Get global logging level */ -CV_EXPORTS_W LogLevel getLogLevel(); +CV_EXPORTS LogLevel getLogLevel(); CV_EXPORTS void registerLogTag(cv::utils::logging::LogTag* plogtag); @@ -43,44 +43,6 @@ CV_EXPORTS void writeLogMessage(LogLevel logLevel, const char* message); /** Write log message */ CV_EXPORTS void writeLogMessageEx(LogLevel logLevel, const char* tag, const char* file, int line, const char* func, const char* message); -/** - * @brief Function pointer type for writeLogMessage. Used by replaceWriteLogMessage. - */ -typedef void (*WriteLogMessageFuncType)(LogLevel, const char*); - -/** - * @brief Function pointer type for writeLogMessageEx. Used by replaceWriteLogMessageEx. - */ -typedef void (*WriteLogMessageExFuncType)(LogLevel, const char*, const char*, int, const char*, const char*); - -/** - * @brief Replaces the OpenCV writeLogMessage function with a user-defined function. - * @note The user-defined function must have the same signature as writeLogMessage. - * @note The user-defined function must accept arguments that can be potentially null. - * @note The user-defined function must be thread-safe, as OpenCV logging may be called - * from multiple threads. - * @note The user-defined function must not perform any action that can trigger - * deadlocks or infinite loop. Many OpenCV functions are not re-entrant. - * @note Once replaced, logs will not go through the OpenCV writeLogMessage function. - * @note To restore, call this function with a nullptr. - */ -CV_EXPORTS void replaceWriteLogMessage(WriteLogMessageFuncType f); - -/** - * @brief Replaces the OpenCV writeLogMessageEx function with a user-defined function. - * @note The user-defined function must have the same signature as writeLogMessage. - * @note The user-defined function must accept arguments that can be potentially null. - * @note The user-defined function must be thread-safe, as OpenCV logging may be called - * from multiple threads. - * @note The user-defined function must not perform any action that can trigger - * deadlocks or infinite loop. Many OpenCV functions are not re-entrant. - * @note Once replaced, logs will not go through any of the OpenCV logging functions - * such as writeLogMessage or writeLogMessageEx, until their respective restore - * methods are called. - * @note To restore, call this function with a nullptr. - */ -CV_EXPORTS void replaceWriteLogMessageEx(WriteLogMessageExFuncType f); - } // namespace struct LogTagAuto diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/version.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/version.hpp index 4c897b060804948909c9812d2061e1591cef2e10..7c5eaa14376865c42eed17ec9f25d3a6d0ffc1a3 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/version.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/version.hpp @@ -6,9 +6,9 @@ #define OPENCV_VERSION_HPP #define CV_VERSION_MAJOR 4 -#define CV_VERSION_MINOR 13 +#define CV_VERSION_MINOR 11 #define CV_VERSION_REVISION 0 -#define CV_VERSION_STATUS "-pre" +#define CV_VERSION_STATUS "" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/vsx_utils.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/vsx_utils.hpp index aafc6c07b176051716d626b07ea61b84dff9f58e..79a1074d59ff334fe083625b4537bcc018aa2af9 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/vsx_utils.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/core/vsx_utils.hpp @@ -257,27 +257,8 @@ VSX_IMPL_1VRG(vec_udword2, vec_udword2, vpopcntd, vec_popcntu) VSX_IMPL_1VRG(vec_udword2, vec_dword2, vpopcntd, vec_popcntu) // converts between single and double-precision -// vec_floate and vec_doubleo are available since Power10 and z14 -#if defined(__POWER10__) || (defined(__powerpc64__) && defined(__ARCH_PWR10__) -// Use VSX double<->float conversion instructions (if supported by the architecture) - VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, vec_floate) - VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, vec_doubleo) -#else -// Fallback: implement vec_cvfo using scalar operations (to ensure successful linking) - static inline vec_float4 vec_cvfo(const vec_double2& a) - { - float r0 = static_cast(reinterpret_cast(&a)[0]); - float r1 = static_cast(reinterpret_cast(&a)[1]); - return (vec_float4){r0, 0.f, r1, 0.f}; - } - - static inline vec_double2 vec_cvfo(const vec_float4& a) - { - double r0 = static_cast(reinterpret_cast(&a)[0]); - double r1 = static_cast(reinterpret_cast(&a)[2]); - return (vec_double2){r0, r1}; - } -#endif +VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, __builtin_vsx_xvcvdpsp) +VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, __builtin_vsx_xvcvspdp) // converts word and doubleword to double-precision #undef vec_ctd @@ -418,6 +399,10 @@ VSX_REDIRECT_1RG(vec_ushort8, vec_ushort8, vec_popcntu, vec_popcnt) VSX_REDIRECT_1RG(vec_uint4, vec_uint4, vec_popcntu, vec_popcnt) VSX_REDIRECT_1RG(vec_udword2, vec_udword2, vec_popcntu, vec_popcnt) +// converts between single and double precision +VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, __builtin_vsx_xvcvdpsp) +VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, __builtin_vsx_xvcvspdp) + // converts word and doubleword to double-precision #ifdef vec_ctd # undef vec_ctd diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/cvconfig.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/cvconfig.h index 78290edcd31b158f63f4dd98ac7171a578bd9a1d..ad5233e70d9804bf14d6ca332816046c105d427c 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/cvconfig.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/cvconfig.h @@ -93,7 +93,7 @@ /* #undef HAVE_NVCUVENC */ /* OpenCL Support */ -/* #undef HAVE_OPENCL */ +#define HAVE_OPENCL /* #undef HAVE_OPENCL_STATIC */ /* #undef HAVE_OPENCL_SVM */ @@ -101,7 +101,7 @@ /* #undef HAVE_OPENCL_D3D11_NV */ /* OpenEXR codec */ -/* #undef HAVE_OPENEXR */ +#define HAVE_OPENEXR /* OpenGL support*/ /* #undef HAVE_OPENGL */ diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/dnn.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/dnn.hpp index fbe5044fef191fd66a7fd77fc8fa0c37936854a8..0077ae485389b2e2fbb50c85a7d65644b981400b 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/dnn.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/dnn.hpp @@ -72,7 +72,7 @@ CV__DNN_INLINE_NS_BEGIN //! DNN_BACKEND_DEFAULT equals to OPENCV_DNN_BACKEND_DEFAULT, which can be defined using CMake or a configuration parameter DNN_BACKEND_DEFAULT = 0, DNN_BACKEND_HALIDE, - DNN_BACKEND_INFERENCE_ENGINE, //!< Intel OpenVINO computational backend, supported targets: CPU, OPENCL, OPENCL_FP16, MYRIAD, HDDL, NPU + DNN_BACKEND_INFERENCE_ENGINE, //!< Intel OpenVINO computational backend //!< @note Tutorial how to build OpenCV with OpenVINO: @ref tutorial_dnn_openvino DNN_BACKEND_OPENCV, DNN_BACKEND_VKCOM, @@ -606,7 +606,7 @@ CV__DNN_INLINE_NS_BEGIN * * @returns index of bound layer (the same as layerId or newly created) */ - CV_WRAP int registerOutput(const std::string& outputName, int layerId, int outputPort); + int registerOutput(const std::string& outputName, int layerId, int outputPort); /** @brief Sets outputs names of the network input pseudo layer. * @@ -1219,16 +1219,16 @@ CV__DNN_INLINE_NS_BEGIN { CV_WRAP Image2BlobParams(); CV_WRAP Image2BlobParams(const Scalar& scalefactor, const Size& size = Size(), const Scalar& mean = Scalar(), - bool swapRB = false, int ddepth = CV_32F, dnn::DataLayout datalayout = DNN_LAYOUT_NCHW, - ImagePaddingMode mode = dnn::DNN_PMODE_NULL, Scalar borderValue = 0.0); + bool swapRB = false, int ddepth = CV_32F, DataLayout datalayout = DNN_LAYOUT_NCHW, + ImagePaddingMode mode = DNN_PMODE_NULL, Scalar borderValue = 0.0); CV_PROP_RW Scalar scalefactor; //!< scalefactor multiplier for input image values. CV_PROP_RW Size size; //!< Spatial size for output image. CV_PROP_RW Scalar mean; //!< Scalar with mean values which are subtracted from channels. CV_PROP_RW bool swapRB; //!< Flag which indicates that swap first and last channels CV_PROP_RW int ddepth; //!< Depth of output blob. Choose CV_32F or CV_8U. - CV_PROP_RW dnn::DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC. - CV_PROP_RW dnn::ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode. + CV_PROP_RW DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC. + CV_PROP_RW ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode. CV_PROP_RW Scalar borderValue; //!< Value used in padding mode for padding. /** @brief Get rectangle coordinates in original image system from rectangle in blob coordinates. diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/version.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/version.hpp index 95bb2f03d1921e33df64bdcfdda1edde85ec964b..5cf0870b444d70e94ea210ab32cfd01c80d6d797 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/version.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/dnn/version.hpp @@ -6,7 +6,7 @@ #define OPENCV_DNN_VERSION_HPP /// Use with major OpenCV version only. -#define OPENCV_DNN_API_VERSION 20251223 +#define OPENCV_DNN_API_VERSION 20241223 #if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS #define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION) diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/features2d.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/features2d.hpp index 567aeeefce70b93b6efba217f1bcf31a26ddc7d5..b4c4dde7121fb58218384b3d779e70a6eb82c280 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/features2d.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/features2d.hpp @@ -687,7 +687,7 @@ public: CV_WRAP static Ptr create( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1, int blockSize=3, bool useHarrisDetector=false, double k=0.04 ); CV_WRAP static Ptr create( int maxCorners, double qualityLevel, double minDistance, - int blockSize, int gradientSize, bool useHarrisDetector=false, double k=0.04 ); + int blockSize, int gradiantSize, bool useHarrisDetector=false, double k=0.04 ); CV_WRAP virtual void setMaxFeatures(int maxFeatures) = 0; CV_WRAP virtual int getMaxFeatures() const = 0; @@ -769,11 +769,6 @@ public: CV_PROP_RW bool filterByConvexity; CV_PROP_RW float minConvexity, maxConvexity; - /** @brief Flag to enable contour collection. - If set to true, the detector will store the contours of the detected blobs in memory, - which can be retrieved after the detect() call using getBlobContours(). - @note Default value is false. - */ CV_PROP_RW bool collectContours; void read( const FileNode& fn ); @@ -787,14 +782,10 @@ public: CV_WRAP virtual SimpleBlobDetector::Params getParams() const = 0; CV_WRAP virtual String getDefaultName() const CV_OVERRIDE; - - /** @brief Returns the contours of the blobs detected during the last call to detect(). - @note The @ref Params::collectContours parameter must be set to true before calling - detect() for this method to return any data. - */ CV_WRAP virtual const std::vector >& getBlobContours() const; }; + /** @brief Class implementing the KAZE keypoint detector and descriptor extractor, described in @cite ABD12 . @note AKAZE descriptor can only be used with KAZE or AKAZE keypoints .. [ABD12] KAZE Features. Pablo diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/autotuned_index.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/autotuned_index.h index 0b02f5670a813704b3168c9ab215b6227c25e8e9..d90f739aff24da2c76159ccb531321191e65d1c1 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/autotuned_index.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/autotuned_index.h @@ -54,7 +54,7 @@ NNIndex* create_index_by_type(const Matrix #endif diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/general.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/general.h index 11ea2af64584d3825465c985a770f15fb679ecf2..e65cba2f8af42863b10de83c97db9e72eeecd956 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/general.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/general.h @@ -54,12 +54,12 @@ public: #define FLANN_THROW(TYPE, STR) throw FLANNException(STR) -//! @endcond - #else #define FLANN_THROW(TYPE, STR) CV_Error(TYPE, STR) #endif +//! @endcond + #endif /* OPENCV_FLANN_GENERAL_H_ */ diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/kmeans_index.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/kmeans_index.h index 7ced99ca81e98276dd9d5717c9fad33db4bf3058..fd7fe2bd39f46092faa2595d8948a28b7ee560a8 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/kmeans_index.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/flann/kmeans_index.h @@ -62,7 +62,7 @@ struct KMeansIndexParams : public IndexParams { KMeansIndexParams(int branching = 32, int iterations = 11, flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, - float cb_index = 0.2f, int trees = 1 ) + float cb_index = 0.2, int trees = 1 ) { (*this)["algorithm"] = FLANN_INDEX_KMEANS; // branching factor diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/core.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/core.hpp index c08e18bb4e45c00653fcf1f54b8d1dbb206a42c5..60bb2c50745800bf02cf44a455453ee5119f1e44 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/core.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/core.hpp @@ -1796,7 +1796,7 @@ contains a 0-based cluster index for the \f$i^{th}\f$ sample. @note - Function textual ID is "org.opencv.core.kmeansND" - - In case of an N-dimensional points' set given, input GMat can have the following traits: + - In case of an N-dimentional points' set given, input GMat can have the following traits: 2 dimensions, a single row or column if there are N channels, or N columns if there is a single channel. Mat should have @ref CV_32F depth. - Although, if GMat with height != 1, width != 1, channels != 1 given as data, n-dimensional @@ -1806,7 +1806,7 @@ samples are considered given in amount of A, where A = height, n = width * chann width = 1, height = A, where A is samples amount, or width = bestLabels.width, height = bestLabels.height if bestLabels given; - the cluster centers are returned as 1-channel GMat with sizes - width = n, height = K, where n is samples' dimensionality and K is clusters' amount. +width = n, height = K, where n is samples' dimentionality and K is clusters' amount. - As one of possible usages, if you want to control the initial labels for each attempt by yourself, you can utilize just the core of the function. To do that, set the number of attempts to 1, initialize labels each time using a custom algorithm, pass them with the @@ -1814,7 +1814,7 @@ of attempts to 1, initialize labels each time using a custom algorithm, pass the @param data Data for clustering. An array of N-Dimensional points with float coordinates is needed. Function can take GArray, GArray for 2D and 3D cases or GMat for any -dimensionality and channels. +dimentionality and channels. @param K Number of clusters to split the set by. @param bestLabels Optional input integer array that can store the supposed initial cluster indices for every sample. Used when ( flags = #KMEANS_USE_INITIAL_LABELS ) flag is set. diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp index 2763d17eafc271f10c505f7363c16c792ed3d7fe..eb5f7847478c658fe50c202296d161ec2ec5f380 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/cpu/gcpukernel.hpp @@ -443,12 +443,7 @@ struct OCVStCallHelper, std::tuple> : template static void call_impl(GCPUContext &ctx, detail::Seq, detail::Seq) { - auto state_ptr = ctx.state().get>(); - if (state_ptr == nullptr) { - CV_Error(cv::Error::StsNullPtr, "Stateful kernel's state is not initialized. " - "Make sure the setup() function properly initializes the state."); - } - auto& st = *state_ptr; + auto& st = *ctx.state().get>(); call_and_postprocess::get(ctx, IIs))...> ::call(st, get_in::get(ctx, IIs)..., get_out::get(ctx, OIs)...); } diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/gmat.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/gmat.hpp index 69cbd094ead32b4c03c9b42f999507f2b00c1ca3..6d6f74ff7f4df9d77ef85620dbeb23c3aa4db3f9 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/gmat.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/gmat.hpp @@ -245,7 +245,7 @@ struct GAPI_EXPORTS_W_SIMPLE GMatDesc static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; } namespace gapi { namespace detail { -/** Checks GMatDesc fields if the passed matrix is a set of n-dimensional points. +/** Checks GMatDesc fields if the passed matrix is a set of n-dimentional points. @param in GMatDesc to check. @param n expected dimensionality. @return the amount of points. In case input matrix can't be described as vector of points diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/imgproc.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/imgproc.hpp index 689c42c82bc90732089c65e7f2dda6771a33bc04..96aaa5a447f5900a7768a0bd48c37d99cd354660 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/imgproc.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/imgproc.hpp @@ -217,7 +217,7 @@ namespace imgproc { GAPI_Assert (in.depth == CV_32S || in.depth == CV_32F); int amount = detail::checkVector(in, 2u); GAPI_Assert(amount != -1 && - "Input Mat can't be described as vector of 2-dimensional points"); + "Input Mat can't be described as vector of 2-dimentional points"); } return empty_gopaque_desc(); } @@ -242,7 +242,7 @@ namespace imgproc { static GOpaqueDesc outMeta(GMatDesc in,DistanceTypes,double,double,double) { int amount = detail::checkVector(in, 2u); GAPI_Assert(amount != -1 && - "Input Mat can't be described as vector of 2-dimensional points"); + "Input Mat can't be described as vector of 2-dimentional points"); return empty_gopaque_desc(); } }; @@ -276,7 +276,7 @@ namespace imgproc { static GOpaqueDesc outMeta(GMatDesc in,int,double,double,double) { int amount = detail::checkVector(in, 3u); GAPI_Assert(amount != -1 && - "Input Mat can't be described as vector of 3-dimensional points"); + "Input Mat can't be described as vector of 3-dimentional points"); return empty_gopaque_desc(); } }; @@ -1235,7 +1235,7 @@ weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . @note - Function textual ID is "org.opencv.imgproc.shape.fitLine2DMat" - - In case of an N-dimensional points' set given, Mat should be 2-dimensional, have a single row + - In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row or column if there are N channels, or have N columns if there is a single channel. @param src Input set of 2D points stored in one of possible containers: Mat, @@ -1307,7 +1307,7 @@ weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . @note - Function textual ID is "org.opencv.imgproc.shape.fitLine3DMat" - - In case of an N-dimensional points' set given, Mat should be 2-dimensional, have a single row + - In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row or column if there are N channels, or have N columns if there is a single channel. @param src Input set of 3D points stored in one of possible containers: Mat, diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/onnx.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/onnx.hpp index f2e2cfac54a0747caca08c22a51723369cf31dbb..eb6316b446818614cfc1eb9b976a812cfdf4a4e5 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/onnx.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/onnx.hpp @@ -20,7 +20,6 @@ #include // GAPI_EXPORTS #include // GKernelPackage #include // Generic -#include namespace cv { namespace gapi { @@ -753,16 +752,8 @@ protected: std::string m_tag; }; -class WorkloadTypeONNX : public WorkloadType {}; -using WorkloadTypeONNXPtr = std::shared_ptr; - } // namespace onnx } // namespace gapi -namespace detail { -template<> struct CompileArgTag { - static const char* tag() { return "gapi.onnx.workload_type"; } -}; -} // namespace detail } // namespace cv #endif // OPENCV_GAPI_INFER_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/ov.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/ov.hpp index d228879fd12a927c966148433ff020d6a96cb904..782792489bacef55e4744822d34bf90c981a5928 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/ov.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/ov.hpp @@ -13,7 +13,6 @@ #include // GAPI_EXPORTS #include // GKernelType[M], GBackend #include // Generic -#include #include @@ -67,8 +66,6 @@ struct ParamDesc { LayerVariantAttr> scale_values; LayerVariantAttr interpolation; - - bool clamp_outputs = false; }; struct CompiledModel { @@ -102,8 +99,6 @@ struct ParamDesc { PluginConfigT config; size_t nireq = 1; - - bool ensure_named_tensors = false; }; // NB: Just helper to avoid code duplication. @@ -210,24 +205,6 @@ public: return *this; } - /** @brief Ensures the model has named tensors. - - This function is used to ensure that all tensors in the model have names. - It goes through all input and output nodes of the model and sets the names - if they are not set. This is neccessary for models with nameless tensors. - - If a tensor does not have a name, it will be assigned a default name - based on the producer node's friendly name. If the producer node has multiple - outputs, the name will be in the form "node_name:N", where N is the output index. - - @param flag If true, then it guarantees that all tensors will have names. - @return reference to this parameter structure. - */ - Params& cfgEnsureNamedTensors(bool flag = true) { - m_desc.ensure_named_tensors = flag; - return *this; - } - /** @brief Specifies tensor layout for an input layer. The function is used to set tensor layout for an input layer. @@ -359,24 +336,6 @@ public: return *this; } - /** @brief Enables or disables clamping of model outputs in the PrePostProcessor. - - By default, output values are clamped to the valid range for the output precision - by the device or plugin. Enabling this option moves clamping to the PrePostProcessor stage. - - @note This feature is only available with OpenVINO 2025.2 and newer. - - @param flag If true, clamping is performed in the PrePostProcessor; - otherwise, it is handled by the device or plugin. - @return reference to this parameter structure. - */ - Params& - cfgClampOutputs(bool flag = true) { - detail::getModelToSetAttrOrThrow(m_desc.kind, "clamp outputs") - .clamp_outputs = std::move(flag); - return *this; - } - /** @brief Specifies the new shape for input layers. The function is used to set new shape for input layers. @@ -565,12 +524,6 @@ public: return *this; } - /** @see ov::Params::cfgEnsureNamedTensors. */ - Params& cfgEnsureNamedTensors(bool flag = true) { - m_desc.ensure_named_tensors = flag; - return *this; - } - /** @see ov::Params::cfgInputTensorLayout. */ Params& cfgInputTensorLayout(std::string layout) { detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") @@ -646,14 +599,6 @@ public: return *this; } - /** @see ov::Params::cfgClampOutputs. */ - Params& - cfgClampOutputs(bool flag = true) { - detail::getModelToSetAttrOrThrow(m_desc.kind, "clamp outputs") - .clamp_outputs = std::move(flag); - return *this; - } - /** @see ov::Params::cfgReshape. */ Params& cfgReshape(std::vector new_shape) { detail::getModelToSetAttrOrThrow(m_desc.kind, "reshape") @@ -746,9 +691,6 @@ namespace wip { namespace ov { */ struct benchmark_mode { }; -class WorkloadTypeOV : public WorkloadType {}; -using WorkloadTypeOVPtr = std::shared_ptr; - } // namespace ov } // namespace wip @@ -760,10 +702,6 @@ namespace detail { static const char* tag() { return "gapi.wip.ov.benchmark_mode"; } }; - template<> struct CompileArgTag - { - static const char* tag() { return "gapi.wip.ov.workload_type"; } - }; } } // namespace cv diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/workload_type.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/workload_type.hpp deleted file mode 100644 index 9f5c5bb51264e3e883083e43ecfa007ccea25409..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/infer/workload_type.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html. -// -// Copyright (C) 2025 Intel Corporation - -#ifndef OPENCV_WORKLOADTYPE_HPP -#define OPENCV_WORKLOADTYPE_HPP - -#include -#include -#include -#include - -using Callback = std::function; - -class WorkloadListener { - Callback callback; -public: - uint64_t id; - WorkloadListener(const Callback &cb, uint64_t listener_id) : callback(cb), id(listener_id) {} - - void operator()(const std::string &type) const { - if (callback) { - callback(type); - } - } - - bool operator==(const WorkloadListener& other) const { - return id == other.id; - } -}; - -class WorkloadType { - std::vector listeners; - uint64_t nextId = 1; -public: - uint64_t addListener(const Callback &cb) { - uint64_t id = nextId++; - listeners.emplace_back(cb, id); - return id; - } - - void removeListener(uint64_t id) { - auto it = std::remove_if(listeners.begin(), listeners.end(), - [id](const WorkloadListener& entry) { return entry.id == id; }); - if (it != listeners.end()) { - listeners.erase(it, listeners.end()); - } - } - - void set(const std::string &type) { - for (const auto &listener : listeners) { - listener(type); - } - } -}; - -#endif // OPENCV_WORKLOADTYPE_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/own/assert.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/own/assert.hpp index 7e9b061f22f456a8160ac62453ab75d9c2a97597..ab2fb896f127d77bb31ac0fb4d0d293853be5b40 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/own/assert.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/own/assert.hpp @@ -19,7 +19,7 @@ #include #define GAPI_Assert CV_Assert -#if !defined(NDEBUG) || defined(CV_STATIC_ANALYSIS) +#if defined _DEBUG || defined CV_STATIC_ANALYSIS # define GAPI_DbgAssert CV_DbgAssert #else # define GAPI_DbgAssert(expr) GAPI_DbgAssertNoOp(expr) diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/pysrc/python_stream_source.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/pysrc/python_stream_source.hpp deleted file mode 100644 index b43dea530532a66673227954579268f06e08f54a..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/pysrc/python_stream_source.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef OPENCV_GAPI_PYSRC_PYTHONSTREAMSOURCE_HPP -#define OPENCV_GAPI_PYSRC_PYTHONSTREAMSOURCE_HPP -#include -#include - -namespace cv { -namespace gapi { -namespace wip { - -/** - * @brief Creates a G-API IStreamSource that delegates to a Python-defined source. - * - * This factory function wraps a Python object (for example, an instance of a class - * implementing a `pull()` and a `descr_of()` method) into a `cv::gapi::wip::IStreamSource`, - * enabling it to be used within a G-API computation graph. The OpenCV Python bindings - * automatically convert the PyObject into a `cv::Ptr`. - * - * @param src - * A `cv::Ptr` that internally holds the original Python object. - * - * @return - * A `cv::Ptr` that wraps the provided Python object. On each frame pull, - * G-API will: - * - Acquire the Python GIL - * - Call the Python object’s `pull()` method - * - Convert the resulting NumPy array to a `cv::Mat` - * - Pass the `cv::Mat` into the G-API pipeline - * - * @note - * In Python, you can use the returned `make_py_src` as follows: - * - * @code{.py} - * class MyClass: - * def __init__(self): - * # Initialize your source - * def pull(self): - * # Return the next frame as a numpy.ndarray or None for end-of-stream - * def descr_of(self): - * # Return a numpy.ndarray that describes the format of the frames - * - * # Create a G-API source from a Python class - * py_src = cv.gapi.wip.make_py_src(MyClass()) - * - * # Define a simple graph: input → copy → output - * g_in = cv.GMat() - * g_out = cv.gapi.copy(g_in) - * graph = cv.GComputation(g_in, g_out) - * - * # Compile the pipeline for streaming and assign the source - * pipeline = graph.compileStreaming() - * pipeline.setSource([py_src]) - * pipeline.start() - * @endcode - */ - -CV_EXPORTS_W cv::Ptr -make_py_src(const cv::Ptr& src); - - -} // namespace wip -} // namespace gapi -} // namespace cv - - -#endif // OPENCV_GAPI_PYSRC_PYTHONSTREAMSOURCE_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/util/any.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/util/any.hpp index 9f0a5618ac570f50a60080dbe6630b5d317a41f1..94451c77171750927412064172851eae8b5e13f5 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/util/any.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/gapi/util/any.hpp @@ -17,7 +17,6 @@ #if defined(_MSC_VER) // disable MSVC warning on "multiple copy constructors specified" - #pragma warning(push) # pragma warning(disable: 4521) #endif @@ -185,7 +184,7 @@ namespace util #if defined(_MSC_VER) // Enable "multiple copy constructors specified" back -# pragma warning(pop) +# pragma warning(default: 4521) #endif #endif // OPENCV_GAPI_UTIL_ANY_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgcodecs.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgcodecs.hpp index bad9f006b50324e58696210fff65641fc7ac0ce0..cd648c2c6e6975aa2557e0e1b3303b899c920f2e 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgcodecs.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgcodecs.hpp @@ -65,7 +65,6 @@ namespace cv //! @{ //! Imread flags -//! @note IMREAD_COLOR_BGR (IMREAD_COLOR) and IMREAD_COLOR_RGB can not be set at the same time. enum ImreadModes { IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation. IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion). @@ -94,10 +93,8 @@ enum ImwriteFlags { IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is -1 - don't use. If JPEG_LIB_VERSION < 70, Not supported. IMWRITE_JPEG_SAMPLING_FACTOR = 7, //!< For JPEG, set sampling factor. See cv::ImwriteJPEGSamplingFactorParams. IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting). - IMWRITE_PNG_STRATEGY = 17, //!< For PNG, One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. - IMWRITE_PNG_BILEVEL = 18, //!< For PNG, Binary level PNG, 0 or 1, default is 0. For APNG, it is not supported. - IMWRITE_PNG_FILTER = 19, //!< For PNG, One of cv::ImwritePNGFilterFlags, default is IMWRITE_PNG_FILTER_SUB. For APNG, it is not supported. - IMWRITE_PNG_ZLIBBUFFER_SIZE = 20, //!< For PNG with libpng, sets the size of the internal zlib compression buffer in bytes, from 6 to 1048576(1024 KiB). Default is 8192(8 KiB). For normal use, 131072(128 KiB) or 262144(256 KiB) may be sufficient. If WITH_SPNG=ON, it is not supported. For APNG, it is not supported. + IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. + IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0. IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1. IMWRITE_EXR_TYPE = (3 << 4) + 0 /* 48 */, //!< override EXR storage type (FLOAT (FP32) is default) IMWRITE_EXR_COMPRESSION = (3 << 4) + 1 /* 49 */, //!< override EXR compression type (ZIP_COMPRESSION = 3 is default) @@ -105,23 +102,22 @@ enum ImwriteFlags { IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. IMWRITE_HDR_COMPRESSION = (5 << 4) + 0 /* 80 */, //!< specify HDR compression IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format - IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set. See ImwriteTiffResolutionUnitFlags. Default is IMWRITE_TIFF_RESOLUTION_UNIT_INCH. + IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI IMWRITE_TIFF_YDPI = 258,//!< For TIFF, use to specify the Y direction DPI IMWRITE_TIFF_COMPRESSION = 259,//!< For TIFF, use to specify the image compression scheme. See cv::ImwriteTiffCompressionFlags. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default. IMWRITE_TIFF_ROWSPERSTRIP = 278,//!< For TIFF, use to specify the number of rows per strip. - IMWRITE_TIFF_PREDICTOR = 317,//!< For TIFF, use to specify predictor. See cv::ImwriteTiffPredictorFlags. Default is IMWRITE_TIFF_PREDICTOR_HORIZONTAL . + IMWRITE_TIFF_PREDICTOR = 317,//!< For TIFF, use to specify predictor. See cv::ImwriteTiffPredictorFlags. IMWRITE_JPEG2000_COMPRESSION_X1000 = 272,//!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000. IMWRITE_AVIF_QUALITY = 512,//!< For AVIF, it can be a quality between 0 and 100 (the higher the better). Default is 95. - IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_16U. Default is 8. - IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and 10(fastest). Default is 9. + IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_32F. Default is 8. + IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and (fastest). Default is 9. IMWRITE_JPEGXL_QUALITY = 640,//!< For JPEG XL, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. If set, distance parameter is re-calicurated from quality level automatically. This parameter request libjxl v0.10 or later. IMWRITE_JPEGXL_EFFORT = 641,//!< For JPEG XL, encoder effort/speed level without affecting decoding speed; it is between 1 (fastest) and 10 (slowest). Default is 7. IMWRITE_JPEGXL_DISTANCE = 642,//!< For JPEG XL, distance level for lossy compression: target max butteraugli distance, lower = higher quality, 0 = lossless; range: 0 .. 25. Default is 1. IMWRITE_JPEGXL_DECODING_SPEED = 643,//!< For JPEG XL, decoding speed tier for the provided options; minimum is 0 (slowest to decode, best quality/density), and maximum is 4 (fastest to decode, at the cost of some quality/density). Default is 0. - IMWRITE_BMP_COMPRESSION = 768, //!< For BMP, use to specify compress parameter for 32bpp image. Default is IMWRITE_BMP_COMPRESSION_BITFIELDS. See cv::ImwriteBMPCompressionFlags. - IMWRITE_GIF_LOOP = 1024, //!< Not functional since 4.12.0. Replaced by cv::Animation::loop_count. - IMWRITE_GIF_SPEED = 1025, //!< Not functional since 4.12.0. Replaced by cv::Animation::durations. + IMWRITE_GIF_LOOP = 1024,//!< For GIF, it can be a loop flag from 0 to 65535. Default is 0 - loop forever. + IMWRITE_GIF_SPEED = 1025,//!< For GIF, it is between 1 (slowest) and 100 (fastest). Default is 96. IMWRITE_GIF_QUALITY = 1026, //!< For GIF, it can be a quality from 1 to 8. Default is 2. See cv::ImwriteGifCompressionFlags. IMWRITE_GIF_DITHER = 1027, //!< For GIF, it can be a quality from -1(most dither) to 3(no dither). Default is 0. IMWRITE_GIF_TRANSPARENCY = 1028, //!< For GIF, the alpha channel lower than this will be set to transparent. Default is 1. @@ -176,16 +172,11 @@ enum ImwriteTiffPredictorFlags { IMWRITE_TIFF_PREDICTOR_NONE = 1, //!< no prediction scheme used IMWRITE_TIFF_PREDICTOR_HORIZONTAL = 2, //!< horizontal differencing IMWRITE_TIFF_PREDICTOR_FLOATINGPOINT = 3 //!< floating point predictor -}; -enum ImwriteTiffResolutionUnitFlags { - IMWRITE_TIFF_RESOLUTION_UNIT_NONE = 1, //!< no absolute unit of measurement. - IMWRITE_TIFF_RESOLUTION_UNIT_INCH = 2, //!< inch - IMWRITE_TIFF_RESOLUTION_UNIT_CENTIMETER = 3, //!< centimeter }; enum ImwriteEXRTypeFlags { - // IMWRITE_EXR_TYPE_UNIT = 0, // not supported + /*IMWRITE_EXR_TYPE_UNIT = 0, //!< not supported */ IMWRITE_EXR_TYPE_HALF = 1, //!< store as HALF (FP16) IMWRITE_EXR_TYPE_FLOAT = 2 //!< store as FP32 (default) }; @@ -219,17 +210,6 @@ enum ImwritePNGFlags { IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. }; -//! Imwrite PNG specific values for IMWRITE_PNG_FILTER parameter key -enum ImwritePNGFilterFlags { - IMWRITE_PNG_FILTER_NONE = 8, //!< Applies no filter to the PNG image (useful when you want to save the raw pixel data without any compression filter). - IMWRITE_PNG_FILTER_SUB = 16, //!< Applies the "sub" filter, which calculates the difference between the current byte and the previous byte in the row. - IMWRITE_PNG_FILTER_UP = 32, //!< applies the "up" filter, which calculates the difference between the current byte and the corresponding byte directly above it. - IMWRITE_PNG_FILTER_AVG = 64, //!< applies the "average" filter, which calculates the average of the byte to the left and the byte above. - IMWRITE_PNG_FILTER_PAETH = 128, //!< applies the "Paeth" filter, a more complex filter that predicts the next pixel value based on neighboring pixels. - IMWRITE_PNG_FAST_FILTERS = (IMWRITE_PNG_FILTER_NONE | IMWRITE_PNG_FILTER_SUB | IMWRITE_PNG_FILTER_UP), //!< This is a combination of IMWRITE_PNG_FILTER_NONE, IMWRITE_PNG_FILTER_SUB, and IMWRITE_PNG_FILTER_UP, typically used for faster compression. - IMWRITE_PNG_ALL_FILTERS = (IMWRITE_PNG_FAST_FILTERS | IMWRITE_PNG_FILTER_AVG | IMWRITE_PNG_FILTER_PAETH) //!< This combines all available filters (NONE, SUB, UP, AVG, and PAETH), which will attempt to apply all of them for the best possible compression. - }; - //! Imwrite PAM specific tupletype flags used to define the 'TUPLETYPE' field of a PAM file. enum ImwritePAMFlags { IMWRITE_PAM_FORMAT_NULL = 0, @@ -246,12 +226,6 @@ enum ImwriteHDRCompressionFlags { IMWRITE_HDR_COMPRESSION_RLE = 1 }; -//! Imwrite BMP specific values for IMWRITE_BMP_COMPRESSION parameter key. -enum ImwriteBMPCompressionFlags { - IMWRITE_BMP_COMPRESSION_RGB = 0, //!< Use BI_RGB. OpenCV v4.12.0 or before supports to encode with this compression only. - IMWRITE_BMP_COMPRESSION_BITFIELDS = 3, //!< Use BI_BITFIELDS. OpenCV v4.13.0 or later can support to encode with this compression. (only for 32 BPP images) -}; - //! Imwrite GIF specific values for IMWRITE_GIF_QUALITY parameter key, if larger than 3, then its related to the size of the color table. enum ImwriteGIFCompressionFlags { IMWRITE_GIF_FAST_NO_DITHER = 1, @@ -264,18 +238,6 @@ enum ImwriteGIFCompressionFlags { IMWRITE_GIF_COLORTABLE_SIZE_256 = 8 }; -enum ImageMetadataType -{ - IMAGE_METADATA_UNKNOWN = -1, // Used when metadata type is unrecognized or not set - - IMAGE_METADATA_EXIF = 0, // EXIF metadata (e.g., camera info, GPS, orientation) - IMAGE_METADATA_XMP = 1, // XMP metadata (eXtensible Metadata Platform - Adobe format) - IMAGE_METADATA_ICCP = 2, // ICC Profile (color profile for color management) - IMAGE_METADATA_CICP = 3, // cICP Profile (video signal type) - - IMAGE_METADATA_MAX = 3 // Highest valid index (usually used for bounds checking) -}; - //! @} imgcodecs_flags /** @brief Represents an animation with multiple frames. @@ -285,25 +247,13 @@ It provides support for looping, background color settings, frame timing, and fr struct CV_EXPORTS_W_SIMPLE Animation { //! Number of times the animation should loop. 0 means infinite looping. - /*! @note At some file format, when N is set, whether it is displayed N or N+1 times depends on the implementation of the user application. This loop times behaviour has not been documented clearly. - * - (GIF) See https://issues.chromium.org/issues/40459899 - * And animated GIF with loop is extended with the Netscape Application Block(NAB), which it not a part of GIF89a specification. See https://en.wikipedia.org/wiki/GIF#Animated_GIF . - * - (WebP) See https://issues.chromium.org/issues/41276895 - */ CV_PROP_RW int loop_count; //! Background color of the animation in BGRA format. CV_PROP_RW Scalar bgcolor; //! Duration for each frame in milliseconds. - /*! @note (GIF) Due to file format limitation - * - Durations must be multiples of 10 milliseconds. Any provided value will be rounded down to the nearest 10ms (e.g., 88ms → 80ms). - * - 0ms(or smaller than expected in user application) duration may cause undefined behavior, e.g. it is handled with default duration. - * - Over 65535 * 10 milliseconds duration is not supported. - */ CV_PROP_RW std::vector durations; //! Vector of frames, where each Mat represents a single frame. CV_PROP_RW std::vector frames; - //! image that can be used for the format in addition to the animation or if animation is not supported in the reader (like in PNG). - CV_PROP_RW Mat still_image; /** @brief Constructs an Animation object with optional loop count and background color. @@ -313,11 +263,11 @@ struct CV_EXPORTS_W_SIMPLE Animation - If a negative value or a value beyond the maximum of `0xffff` (65535) is provided, it is reset to `0` (infinite looping) to maintain valid bounds. - @param bgColor A `Scalar` object representing the background color in BGR format: + @param bgColor A `Scalar` object representing the background color in BGRA format: - Defaults to `Scalar()`, indicating an empty color (usually transparent if supported). - This background color provides a solid fill behind frames that have transparency, ensuring a consistent display appearance. */ - CV_WRAP Animation(int loopCount = 0, Scalar bgColor = Scalar()); + Animation(int loopCount = 0, Scalar bgColor = Scalar()); }; /** @brief Loads an image from a file. @@ -370,7 +320,7 @@ Currently, the following file formats are supported: the environment variable `OPENCV_IO_MAX_IMAGE_PIXELS`. See @ref tutorial_env_reference. @param filename Name of the file to be loaded. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_COLOR_BGR. +@param flags Flag that can take values of `cv::ImreadModes`. */ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR_BGR ); @@ -379,29 +329,12 @@ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR_BGR ); This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts and the return value. @param filename Name of file to be loaded. @param dst object in which the image will be loaded. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_COLOR_BGR. +@param flags Flag that can take values of cv::ImreadModes @note The image passing through the img parameter can be pre-allocated. The memory is reused if the shape and the type match with the load image. */ CV_EXPORTS_W void imread( const String& filename, OutputArray dst, int flags = IMREAD_COLOR_BGR ); -/** @brief Reads an image from a file along with associated metadata. - -This function behaves similarly to cv::imread(), loading an image from the specified file. -In addition to the image pixel data, it also attempts to extract any available metadata -embedded in the file (such as EXIF, XMP, etc.), depending on file format support. - -@note In the case of color images, the decoded images will have the channels stored in **B G R** order. -@param filename Name of the file to be loaded. -@param metadataTypes Output vector with types of metadata chunks returned in metadata, see ImageMetadataType. -@param metadata Output vector of vectors or vector of matrices to store the retrieved metadata. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. - -@return The loaded image as a cv::Mat object. If the image cannot be read, the function returns an empty matrix. -*/ -CV_EXPORTS_W Mat imreadWithMetadata( const String& filename, CV_OUT std::vector& metadataTypes, - OutputArrayOfArrays metadata, int flags = IMREAD_ANYCOLOR); - /** @brief Loads a multi-page image from a file. The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects. @@ -442,19 +375,6 @@ The function imreadanimation loads frames from an animated image file (e.g., GIF */ CV_EXPORTS_W bool imreadanimation(const String& filename, CV_OUT Animation& animation, int start = 0, int count = INT16_MAX); -/** @brief Loads frames from an animated image buffer into an Animation structure. - -The function imdecodeanimation loads frames from an animated image buffer (e.g., GIF, AVIF, APNG, WEBP) into the provided Animation struct. - -@param buf A reference to an InputArray containing the image buffer. -@param animation A reference to an Animation structure where the loaded frames will be stored. It should be initialized before the function is called. -@param start The index of the first frame to load. This is optional and defaults to 0. -@param count The number of frames to load. This is optional and defaults to 32767. - -@return Returns true if the buffer was successfully loaded and frames were extracted; returns false otherwise. -*/ -CV_EXPORTS_W bool imdecodeanimation(InputArray buf, CV_OUT Animation& animation, int start = 0, int count = INT16_MAX); - /** @brief Saves an Animation to a specified file. The function imwriteanimation saves the provided Animation data to the specified file in an animated format. @@ -469,26 +389,6 @@ These parameters are used to specify additional options for the encoding process */ CV_EXPORTS_W bool imwriteanimation(const String& filename, const Animation& animation, const std::vector& params = std::vector()); -/** @brief Encodes an Animation to a memory buffer. - -The function imencodeanimation encodes the provided Animation data into a memory -buffer in an animated format. Supported formats depend on the implementation and -may include formats like GIF, AVIF, APNG, or WEBP. - -@param ext The file extension that determines the format of the encoded data. -@param animation A constant reference to an Animation struct containing the -frames and metadata to be encoded. -@param buf A reference to a vector of unsigned chars where the encoded data will -be stored. -@param params Optional format-specific parameters encoded as pairs (paramId_1, -paramValue_1, paramId_2, paramValue_2, ...). These parameters are used to -specify additional options for the encoding process. Refer to `cv::ImwriteFlags` -for details on possible parameters. - -@return Returns true if the animation was successfully encoded; returns false otherwise. -*/ -CV_EXPORTS_W bool imencodeanimation(const String& ext, const Animation& animation, CV_OUT std::vector& buf, const std::vector& params = std::vector()); - /** @brief Returns the number of images inside the given file The function imcount returns the number of pages in a multi-page image (e.g. TIFF), the number of frames in an animation (e.g. AVIF), and 1 otherwise. @@ -506,25 +406,20 @@ filename extension (see cv::imread for the list of extensions). In general, only single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function, with these exceptions: -- With BMP encoder, 8-bit unsigned (CV_8U) images can be saved. - - BMP images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255. - OpenCV v4.13.0 or later use BI_BITFIELDS compression as default. See IMWRITE_BMP_COMPRESSION. -- With OpenEXR encoder, only 32-bit float (CV_32F) images can be saved. More than 4 channels can be saved. (imread can load it then.) +- With OpenEXR encoder, only 32-bit float (CV_32F) images can be saved. - 8-bit unsigned (CV_8U) images are not supported. - With Radiance HDR encoder, non 64-bit float (CV_64F) images can be saved. - All images will be converted to 32-bit float (CV_32F). - With JPEG 2000 encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With JPEG XL encoder, 8-bit unsigned (CV_8U), 16-bit unsigned (CV_16U) and 32-bit float(CV_32F) images can be saved. - JPEG XL images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) / 32-bit float 4-channel (CV_32FC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255/65535/1.0. + To do this, create 8-bit (or 16-bit, 32-bit float) 4-channel image BGRA, where the alpha channel goes last. + Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535/1.0. - With PAM encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With PNG encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - - PNG images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255/65535(see the code sample below). + - PNG images with an alpha channel can be saved using this function. To do this, create + 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels + should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535 (see the code sample below). - With PGM/PPM encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - With TIFF encoder, 8-bit unsigned (CV_8U), 8-bit signed (CV_8S), 16-bit unsigned (CV_16U), 16-bit signed (CV_16S), @@ -533,16 +428,6 @@ can be saved using this function, with these exceptions: - Multiple images (vector of Mat) can be saved in TIFF format (see the code sample below). - 32-bit float 3-channel (CV_32FC3) TIFF images will be saved using the LogLuv high dynamic range encoding (4 bytes per pixel) -- With GIF encoder, 8-bit unsigned (CV_8U) images can be saved. - - GIF images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255. - - 8-bit single-channel images (CV_8UC1) are not supported due to GIF's limitation to indexed color formats. -- With AVIF encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved. - - CV_16U images can be saved as only 10-bit or 12-bit (not 16-bit). See IMWRITE_AVIF_DEPTH. - - AVIF images with an alpha channel can be saved using this function. - To achieve this, create an 8-bit 4-channel (CV_8UC4) / 16-bit 4-channel (CV_16UC4) BGRA image, ensuring the alpha channel is the last component. - Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255 (8-bit) / 1023 (10-bit) / 4095 (12-bit) (see the code sample below). If the image format is not supported, the image will be converted to 8-bit unsigned (CV_8U) and saved that way. @@ -556,25 +441,10 @@ It also demonstrates how to save multiple images in a TIFF file: @param filename Name of the file. @param img (Mat or vector of Mat) Image or Images to be saved. @param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags -@return true if the image is successfully written to the specified file; false otherwise. */ CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector()); -/** @brief Saves an image to a specified file with metadata - -The function imwriteWithMetadata saves the image to the specified file. It does the same thing as imwrite, but additionally writes metadata if the corresponding format supports it. -@param filename Name of the file. As with imwrite, image format is determined by the file extension. -@param img (Mat or vector of Mat) Image or Images to be saved. -@param metadataTypes Vector with types of metadata chucks stored in metadata to write, see ImageMetadataType. -@param metadata Vector of vectors or vector of matrices with chunks of metadata to store into the file -@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags -*/ -CV_EXPORTS_W bool imwriteWithMetadata( const String& filename, InputArray img, - const std::vector& metadataTypes, - InputArrayOfArrays& metadata, - const std::vector& params = std::vector()); - //! @brief multi-image overload for bindings CV_WRAP static inline bool imwritemulti(const String& filename, InputArrayOfArrays img, @@ -592,31 +462,13 @@ See cv::imread for the list of supported formats and flags description. @note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. */ CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); -/** @brief Reads an image from a memory buffer and extracts associated metadata. - -This function decodes an image from the specified memory buffer. If the buffer is too short or -contains invalid data, the function returns an empty matrix ( Mat::data==NULL ). - -See cv::imread for the list of supported formats and flags description. - -@note In the case of color images, the decoded images will have the channels stored in **B G R** order. -@param buf Input array or vector of bytes containing the encoded image data. -@param metadataTypes Output vector with types of metadata chucks returned in metadata, see cv::ImageMetadataType -@param metadata Output vector of vectors or vector of matrices to store the retrieved metadata -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. - -@return The decoded image as a cv::Mat object. If decoding fails, the function returns an empty matrix. -*/ -CV_EXPORTS_W Mat imdecodeWithMetadata( InputArray buf, CV_OUT std::vector& metadataTypes, - OutputArrayOfArrays metadata, int flags = IMREAD_ANYCOLOR ); - /** @overload @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. +@param flags The same flags as in cv::imread, see cv::ImreadModes. @param dst The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. In case of decoder failure the function returns empty cv::Mat object, but does not release user-provided dst buffer. @@ -632,7 +484,7 @@ See cv::imreadmulti for the list of supported formats and flags description. @note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags Flag that can take values of cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. @param mats A vector of Mat objects holding each page, if more than one. @param range A continuous selection of pages. */ @@ -652,24 +504,6 @@ CV_EXPORTS_W bool imencode( const String& ext, InputArray img, CV_OUT std::vector& buf, const std::vector& params = std::vector()); -/** @brief Encodes an image into a memory buffer. - -The function imencode compresses the image and stores it in the memory buffer that is resized to fit the -result. See cv::imwrite for the list of supported formats and flags description. - -@param ext File extension that defines the output format. Must include a leading period. -@param img Image to be compressed. -@param metadataTypes Vector with types of metadata chucks stored in metadata to write, see ImageMetadataType. -@param metadata Vector of vectors or vector of matrices with chunks of metadata to store into the file -@param buf Output buffer resized to fit the compressed image. -@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags. -*/ -CV_EXPORTS_W bool imencodeWithMetadata( const String& ext, InputArray img, - const std::vector& metadataTypes, - InputArrayOfArrays metadata, - CV_OUT std::vector& buf, - const std::vector& params = std::vector()); - /** @brief Encodes array of images into a memory buffer. The function is analog to cv::imencode for in-memory multi-page image compression. @@ -693,7 +527,7 @@ This can be useful for verifying support for a given image format before attempt @return true if an image reader for the specified file is available and the file can be opened, false otherwise. @note The function checks the availability of image codecs that are either built into OpenCV or dynamically loaded. -It does not load the image codec implementation and decode data, but uses signature check. +It does not check for the actual existence of the file but rather the ability to read the specified file type. If the file cannot be opened or the format is unsupported, the function will return false. @sa cv::haveImageWriter, cv::imread, cv::imdecode diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc.hpp index 4250625bb4ca433a0aacb57a1b91dc98af669b0f..eb968b9e40deb716f6a65769b3ff730c786e6840 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc.hpp @@ -44,6 +44,12 @@ #define OPENCV_IMGPROC_HPP #include "opencv2/core.hpp" +#include "opencv2/imgproc/cust_ncc.h" +#include "opencv2/imgproc/cust_threshold_s16.h" +#include "opencv2/imgproc/cust_threshold_u16.h" +#include "opencv2/imgproc/cust_filter_and_csc.h" +#include "opencv2/imgproc/cust_mag_and_ang.h" + /** @defgroup imgproc Image Processing @@ -118,7 +124,7 @@ This module offers a comprehensive suite of image processing functions, enabling coordinates needs to be retrieved. In the simplest case, the coordinates can be just rounded to the nearest integer coordinates and the corresponding pixel can be used. This is called a nearest-neighbor interpolation. However, a better result can be achieved by using more - sophisticated [interpolation methods](https://en.wikipedia.org/wiki/Multivariate_interpolation) , + sophisticated [interpolation methods](http://en.wikipedia.org/wiki/Multivariate_interpolation) , where a polynomial function is fit into some neighborhood of the computed pixel \f$(f_x(x,y), f_y(x,y))\f$, and then the value of the polynomial at \f$(f_x(x,y), f_y(x,y))\f$ is taken as the interpolated pixel value. In OpenCV, you can choose between several interpolation methods. See @@ -235,9 +241,8 @@ enum MorphShapes { MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] MORPH_CROSS = 1, //!< a cross-shaped structuring element: //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f] - MORPH_ELLIPSE = 2, //!< an elliptic structuring element, that is, a filled ellipse inscribed + MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed //!< into the rectangle Rect(0, 0, esize.width, esize.height) - MORPH_DIAMOND = 3 //!< a diamond structuring element defined by Manhattan distance }; //! @} imgproc_filter @@ -330,8 +335,7 @@ enum ThresholdTypes { THRESH_TOZERO_INV = 4, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f] THRESH_MASK = 7, THRESH_OTSU = 8, //!< flag, use Otsu algorithm to choose the optimal threshold value - THRESH_TRIANGLE = 16, //!< flag, use Triangle algorithm to choose the optimal threshold value - THRESH_DRYRUN = 128 //!< flag, compute threshold only (useful for OTSU/TRIANGLE) but does not actually run thresholding + THRESH_TRIANGLE = 16 //!< flag, use Triangle algorithm to choose the optimal threshold value }; //! adaptive threshold algorithm @@ -533,153 +537,149 @@ enum HistCompMethods { /** the color conversion codes @see @ref imgproc_color_conversions -@note The source image (src) must be of an appropriate type for the desired color conversion. -- `[8U]` means to support `CV_8U` src type. -- `[16U]` means to support `CV_16U` src type. -- `[32F]` means to support `CV_32F` src type. @ingroup imgproc_color_conversions */ enum ColorConversionCodes { - COLOR_BGR2BGRA = 0, //!< [8U/16U/32F] add alpha channel to RGB or BGR image - COLOR_RGB2RGBA = COLOR_BGR2BGRA, //!< [8U/16U/32F] - - COLOR_BGRA2BGR = 1, //!< [8U/16U/32F] remove alpha channel from RGB or BGR image - COLOR_RGBA2RGB = COLOR_BGRA2BGR, //!< [8U/16U/32F] - - COLOR_BGR2RGBA = 2, //!< [8U/16U/32F] convert between RGB and BGR color spaces (with or without alpha channel) - COLOR_RGB2BGRA = COLOR_BGR2RGBA, //!< [8U/16U/32F] - - COLOR_RGBA2BGR = 3, //!< [8U/16U/32F] - COLOR_BGRA2RGB = COLOR_RGBA2BGR, //!< [8U/16U/32F] - - COLOR_BGR2RGB = 4, //!< [8U/16U/32F] - COLOR_RGB2BGR = COLOR_BGR2RGB, //!< [8U/16U/32F] - - COLOR_BGRA2RGBA = 5, //!< [8U/16U/32F] - COLOR_RGBA2BGRA = COLOR_BGRA2RGBA, //!< [8U/16U/32F] - - COLOR_BGR2GRAY = 6, //!< [8U/16U/32F] convert between RGB/BGR and grayscale, @ref color_convert_rgb_gray "color conversions" - COLOR_RGB2GRAY = 7, //!< [8U/16U/32F] - COLOR_GRAY2BGR = 8, //!< [8U/16U/32F] - COLOR_GRAY2RGB = COLOR_GRAY2BGR, //!< [8U/16U/32F] - COLOR_GRAY2BGRA = 9, //!< [8U/16U/32F] - COLOR_GRAY2RGBA = COLOR_GRAY2BGRA, //!< [8U/16U/32F] - COLOR_BGRA2GRAY = 10, //!< [8U/16U/32F] - COLOR_RGBA2GRAY = 11, //!< [8U/16U/32F] - - COLOR_BGR2BGR565 = 12, //!< [8U] convert between RGB/BGR and BGR565 (16-bit images) - COLOR_RGB2BGR565 = 13, //!< [8U] - COLOR_BGR5652BGR = 14, //!< [8U] - COLOR_BGR5652RGB = 15, //!< [8U] - COLOR_BGRA2BGR565 = 16, //!< [8U] - COLOR_RGBA2BGR565 = 17, //!< [8U] - COLOR_BGR5652BGRA = 18, //!< [8U] - COLOR_BGR5652RGBA = 19, //!< [8U] - - COLOR_GRAY2BGR565 = 20, //!< [8U] convert between grayscale to BGR565 (16-bit images) - COLOR_BGR5652GRAY = 21, //!< [8U] - - COLOR_BGR2BGR555 = 22, //!< [8U] convert between RGB/BGR and BGR555 (16-bit images) - COLOR_RGB2BGR555 = 23, //!< [8U] - COLOR_BGR5552BGR = 24, //!< [8U] - COLOR_BGR5552RGB = 25, //!< [8U] - COLOR_BGRA2BGR555 = 26, //!< [8U] - COLOR_RGBA2BGR555 = 27, //!< [8U] - COLOR_BGR5552BGRA = 28, //!< [8U] - COLOR_BGR5552RGBA = 29, //!< [8U] - - COLOR_GRAY2BGR555 = 30, //!< [8U] convert between grayscale and BGR555 (16-bit images) - COLOR_BGR5552GRAY = 31, //!< [8U] - - COLOR_BGR2XYZ = 32, //!< [8U/16U/32F] convert RGB/BGR to CIE XYZ, @ref color_convert_rgb_xyz "color conversions" - COLOR_RGB2XYZ = 33, //!< [8U/16U/32F] - COLOR_XYZ2BGR = 34, //!< [8U/16U/32F] - COLOR_XYZ2RGB = 35, //!< [8U/16U/32F] - - COLOR_BGR2YCrCb = 36, //!< [8U/16U/32F] convert RGB/BGR to luma-chroma (aka YCC), @ref color_convert_rgb_ycrcb "color conversions" - COLOR_RGB2YCrCb = 37, //!< [8U/16U/32F] - COLOR_YCrCb2BGR = 38, //!< [8U/16U/32F] - COLOR_YCrCb2RGB = 39, //!< [8U/16U/32F] - - COLOR_BGR2HSV = 40, //!< [8U/32F] convert RGB/BGR to HSV (hue saturation value) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hsv "color conversions" - COLOR_RGB2HSV = 41, //!< [8U/32F] - - COLOR_BGR2Lab = 44, //!< [8U/32F] convert RGB/BGR to CIE Lab, @ref color_convert_rgb_lab "color conversions" - COLOR_RGB2Lab = 45, //!< [8U/32F] - - COLOR_BGR2Luv = 50, //!< [8U/32F] convert RGB/BGR to CIE Luv, @ref color_convert_rgb_luv "color conversions" - COLOR_RGB2Luv = 51, //!< [8U/32F] - COLOR_BGR2HLS = 52, //!< [8U/32F] convert RGB/BGR to HLS (hue lightness saturation) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hls "color conversions" - COLOR_RGB2HLS = 53, //!< [8U/32F] - - COLOR_HSV2BGR = 54, //!< [8U/32F] backward conversions HSV to RGB/BGR with H range 0..180 if 8 bit image - COLOR_HSV2RGB = 55, //!< [8U/32F] - - COLOR_Lab2BGR = 56, //!< [8U/32F] - COLOR_Lab2RGB = 57, //!< [8U/32F] - COLOR_Luv2BGR = 58, //!< [8U/32F] - COLOR_Luv2RGB = 59, //!< [8U/32F] - COLOR_HLS2BGR = 60, //!< [8U/32F] backward conversions HLS to RGB/BGR with H range 0..180 if 8 bit image - COLOR_HLS2RGB = 61, //!< [8U/32F] - - COLOR_BGR2HSV_FULL = 66, //!< [8U/32F] convert RGB/BGR to HSV (hue saturation value) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hsv "color conversions" - COLOR_RGB2HSV_FULL = 67, //!< [8U/32F] - COLOR_BGR2HLS_FULL = 68, //!< [8U/32F] convert RGB/BGR to HLS (hue lightness saturation) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hls "color conversions" - COLOR_RGB2HLS_FULL = 69, //!< [8U/32F] - - COLOR_HSV2BGR_FULL = 70, //!< [8U/32F] backward conversions HSV to RGB/BGR with H range 0..255 if 8 bit image - COLOR_HSV2RGB_FULL = 71, //!< [8U/32F] - COLOR_HLS2BGR_FULL = 72, //!< [8U/32F] backward conversions HLS to RGB/BGR with H range 0..255 if 8 bit image - COLOR_HLS2RGB_FULL = 73, //!< [8U/32F] - - COLOR_LBGR2Lab = 74, //!< [8U/32F] - COLOR_LRGB2Lab = 75, //!< [8U/32F] - COLOR_LBGR2Luv = 76, //!< [8U/32F] - COLOR_LRGB2Luv = 77, //!< [8U/32F] - - COLOR_Lab2LBGR = 78, //!< [8U/32F] - COLOR_Lab2LRGB = 79, //!< [8U/32F] - COLOR_Luv2LBGR = 80, //!< [8U/32F] - COLOR_Luv2LRGB = 81, //!< [8U/32F] - - COLOR_BGR2YUV = 82, //!< [8U/16U/32F] convert between RGB/BGR and YUV - COLOR_RGB2YUV = 83, //!< [8U/16U/32F] - COLOR_YUV2BGR = 84, //!< [8U/16U/32F] - COLOR_YUV2RGB = 85, //!< [8U/16U/32F] - - COLOR_YUV2RGB_NV12 = 90, //!< [8U] convert between 4:2:0-subsampled YUV NV12 and RGB, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_NV12 = 91, //!< [8U] convert between 4:2:0-subsampled YUV NV12 and BGR, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGB_NV21 = 92, //!< [8U] convert between 4:2:0-subsampled YUV NV21 and RGB, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_NV21 = 93, //!< [8U] convert between 4:2:0-subsampled YUV NV21 and BGR, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2BGRA = 0, //!< add alpha channel to RGB or BGR image + COLOR_RGB2RGBA = COLOR_BGR2BGRA, + + COLOR_BGRA2BGR = 1, //!< remove alpha channel from RGB or BGR image + COLOR_RGBA2RGB = COLOR_BGRA2BGR, + + COLOR_BGR2RGBA = 2, //!< convert between RGB and BGR color spaces (with or without alpha channel) + COLOR_RGB2BGRA = COLOR_BGR2RGBA, + + COLOR_RGBA2BGR = 3, + COLOR_BGRA2RGB = COLOR_RGBA2BGR, + + COLOR_BGR2RGB = 4, + COLOR_RGB2BGR = COLOR_BGR2RGB, + + COLOR_BGRA2RGBA = 5, + COLOR_RGBA2BGRA = COLOR_BGRA2RGBA, + + COLOR_BGR2GRAY = 6, //!< convert between RGB/BGR and grayscale, @ref color_convert_rgb_gray "color conversions" + COLOR_RGB2GRAY = 7, + COLOR_GRAY2BGR = 8, + COLOR_GRAY2RGB = COLOR_GRAY2BGR, + COLOR_GRAY2BGRA = 9, + COLOR_GRAY2RGBA = COLOR_GRAY2BGRA, + COLOR_BGRA2GRAY = 10, + COLOR_RGBA2GRAY = 11, + + COLOR_BGR2BGR565 = 12, //!< convert between RGB/BGR and BGR565 (16-bit images) + COLOR_RGB2BGR565 = 13, + COLOR_BGR5652BGR = 14, + COLOR_BGR5652RGB = 15, + COLOR_BGRA2BGR565 = 16, + COLOR_RGBA2BGR565 = 17, + COLOR_BGR5652BGRA = 18, + COLOR_BGR5652RGBA = 19, + + COLOR_GRAY2BGR565 = 20, //!< convert between grayscale to BGR565 (16-bit images) + COLOR_BGR5652GRAY = 21, + + COLOR_BGR2BGR555 = 22, //!< convert between RGB/BGR and BGR555 (16-bit images) + COLOR_RGB2BGR555 = 23, + COLOR_BGR5552BGR = 24, + COLOR_BGR5552RGB = 25, + COLOR_BGRA2BGR555 = 26, + COLOR_RGBA2BGR555 = 27, + COLOR_BGR5552BGRA = 28, + COLOR_BGR5552RGBA = 29, + + COLOR_GRAY2BGR555 = 30, //!< convert between grayscale and BGR555 (16-bit images) + COLOR_BGR5552GRAY = 31, + + COLOR_BGR2XYZ = 32, //!< convert RGB/BGR to CIE XYZ, @ref color_convert_rgb_xyz "color conversions" + COLOR_RGB2XYZ = 33, + COLOR_XYZ2BGR = 34, + COLOR_XYZ2RGB = 35, + + COLOR_BGR2YCrCb = 36, //!< convert RGB/BGR to luma-chroma (aka YCC), @ref color_convert_rgb_ycrcb "color conversions" + COLOR_RGB2YCrCb = 37, + COLOR_YCrCb2BGR = 38, + COLOR_YCrCb2RGB = 39, + + COLOR_BGR2HSV = 40, //!< convert RGB/BGR to HSV (hue saturation value) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hsv "color conversions" + COLOR_RGB2HSV = 41, + + COLOR_BGR2Lab = 44, //!< convert RGB/BGR to CIE Lab, @ref color_convert_rgb_lab "color conversions" + COLOR_RGB2Lab = 45, + + COLOR_BGR2Luv = 50, //!< convert RGB/BGR to CIE Luv, @ref color_convert_rgb_luv "color conversions" + COLOR_RGB2Luv = 51, + COLOR_BGR2HLS = 52, //!< convert RGB/BGR to HLS (hue lightness saturation) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hls "color conversions" + COLOR_RGB2HLS = 53, + + COLOR_HSV2BGR = 54, //!< backward conversions HSV to RGB/BGR with H range 0..180 if 8 bit image + COLOR_HSV2RGB = 55, + + COLOR_Lab2BGR = 56, + COLOR_Lab2RGB = 57, + COLOR_Luv2BGR = 58, + COLOR_Luv2RGB = 59, + COLOR_HLS2BGR = 60, //!< backward conversions HLS to RGB/BGR with H range 0..180 if 8 bit image + COLOR_HLS2RGB = 61, + + COLOR_BGR2HSV_FULL = 66, //!< convert RGB/BGR to HSV (hue saturation value) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hsv "color conversions" + COLOR_RGB2HSV_FULL = 67, + COLOR_BGR2HLS_FULL = 68, //!< convert RGB/BGR to HLS (hue lightness saturation) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hls "color conversions" + COLOR_RGB2HLS_FULL = 69, + + COLOR_HSV2BGR_FULL = 70, //!< backward conversions HSV to RGB/BGR with H range 0..255 if 8 bit image + COLOR_HSV2RGB_FULL = 71, + COLOR_HLS2BGR_FULL = 72, //!< backward conversions HLS to RGB/BGR with H range 0..255 if 8 bit image + COLOR_HLS2RGB_FULL = 73, + + COLOR_LBGR2Lab = 74, + COLOR_LRGB2Lab = 75, + COLOR_LBGR2Luv = 76, + COLOR_LRGB2Luv = 77, + + COLOR_Lab2LBGR = 78, + COLOR_Lab2LRGB = 79, + COLOR_Luv2LBGR = 80, + COLOR_Luv2LRGB = 81, + + COLOR_BGR2YUV = 82, //!< convert between RGB/BGR and YUV + COLOR_RGB2YUV = 83, + COLOR_YUV2BGR = 84, + COLOR_YUV2RGB = 85, + + COLOR_YUV2RGB_NV12 = 90, //!< convert between 4:2:0-subsampled YUV NV12 and RGB, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_NV12 = 91, //!< convert between 4:2:0-subsampled YUV NV12 and BGR, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_NV21 = 92, //!< convert between 4:2:0-subsampled YUV NV21 and RGB, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_NV21 = 93, //!< convert between 4:2:0-subsampled YUV NV21 and BGR, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, //!< synonym to NV21 COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, //!< synonym to NV21 - COLOR_YUV2RGBA_NV12 = 94, //!< [8U] convert between 4:2:0-subsampled YUV NV12 and RGBA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_NV12 = 95, //!< [8U] convert between 4:2:0-subsampled YUV NV12 and BGRA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGBA_NV21 = 96, //!< [8U] convert between 4:2:0-subsampled YUV NV21 and RGBA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_NV21 = 97, //!< [8U] convert between 4:2:0-subsampled YUV NV21 and BGRA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_NV12 = 94, //!< convert between 4:2:0-subsampled YUV NV12 and RGBA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_NV12 = 95, //!< convert between 4:2:0-subsampled YUV NV12 and BGRA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_NV21 = 96, //!< convert between 4:2:0-subsampled YUV NV21 and RGBA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_NV21 = 97, //!< convert between 4:2:0-subsampled YUV NV21 and BGRA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, //!< synonym to NV21 COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, //!< synonym to NV21 - COLOR_YUV2RGB_YV12 = 98, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and RGB, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_YV12 = 99, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and BGR, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGB_IYUV = 100, //!< [8U] convert between 4:2:0-subsampled YUV IYUV and RGB, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_IYUV = 101, //!< [8U] convert between 4:2:0-subsampled YUV IYUV and BGR, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_YV12 = 98, //!< convert between 4:2:0-subsampled YUV YV12 and RGB, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YV12 = 99, //!< convert between 4:2:0-subsampled YUV YV12 and BGR, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_IYUV = 100, //!< convert between 4:2:0-subsampled YUV IYUV and RGB, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_IYUV = 101, //!< convert between 4:2:0-subsampled YUV IYUV and BGR, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, //!< synonym to IYUV COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, //!< synonym to IYUV COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, //!< synonym to YV12 COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, //!< synonym to YV12 - COLOR_YUV2RGBA_YV12 = 102, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_YV12 = 103, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGBA_IYUV = 104, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_IYUV = 105, //!< [8U] convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_YV12 = 102, //!< convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YV12 = 103, //!< convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_IYUV = 104, //!< convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_IYUV = 105, //!< convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, //!< synonym to IYUV COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, //!< synonym to IYUV COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, //!< synonym to YV12 COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, //!< synonym to YV12 - COLOR_YUV2GRAY_420 = 106, //!< [8U] extract Y channel from YUV 4:2:0 image + COLOR_YUV2GRAY_420 = 106, //!< extract Y channel from YUV 4:2:0 image COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 @@ -688,8 +688,8 @@ enum ColorConversionCodes { COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 - COLOR_YUV2RGB_UYVY = 107, //!< [8U] convert between YUV UYVY and RGB, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_UYVY = 108, //!< [8U] convert between YUV UYVY and BGR, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_UYVY = 107, //!< convert between YUV UYVY and RGB, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_UYVY = 108, //!< convert between YUV UYVY and BGR, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x //COLOR_YUV2RGB_VYUY = 109, //!< convert between YUV VYUY and RGB, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x //COLOR_YUV2BGR_VYUY = 110, //!< convert between YUV VYUY and BGR, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, //!< synonym to UYVY @@ -697,35 +697,35 @@ enum ColorConversionCodes { COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, //!< synonym to UYVY COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, //!< synonym to UYVY - COLOR_YUV2RGBA_UYVY = 111, //!< [8U] convert between YUV UYVY and RGBA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_UYVY = 112, //!< [8U] convert between YUV UYVY and BGRA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x - //COLOR_YUV2RGBA_VYUY = 113, //!< [8U] convert between YUV VYUY and RGBA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x - //COLOR_YUV2BGRA_VYUY = 114, //!< [8U] convert between YUV VYUY and BGRA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_UYVY = 111, //!< convert between YUV UYVY and RGBA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_UYVY = 112, //!< convert between YUV UYVY and BGRA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2RGBA_VYUY = 113, //!< convert between YUV VYUY and RGBA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2BGRA_VYUY = 114, //!< convert between YUV VYUY and BGRA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, //!< synonym to UYVY COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, //!< synonym to UYVY COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, //!< synonym to UYVY COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, //!< synonym to UYVY - COLOR_YUV2RGB_YUY2 = 115, //!< [8U] convert between YUV YUY2 and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_YUY2 = 116, //!< [8U] convert between YUV YUY2 and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGB_YVYU = 117, //!< [8U] convert between YUV YVYU and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGR_YVYU = 118, //!< [8U] convert between YUV YVYU and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_YUY2 = 115, //!< convert between YUV YUY2 and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YUY2 = 116, //!< convert between YUV YUY2 and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_YVYU = 117, //!< convert between YUV YVYU and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YVYU = 118, //!< convert between YUV YVYU and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, //!< synonym to YUY2 COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, //!< synonym to YUY2 COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, //!< synonym to YUY2 COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, //!< synonym to YUY2 - COLOR_YUV2RGBA_YUY2 = 119, //!< [8U] convert between YUV YUY2 and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_YUY2 = 120, //!< [8U] convert between YUV YUY2 and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2RGBA_YVYU = 121, //!< [8U] convert between YUV YVYU and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x - COLOR_YUV2BGRA_YVYU = 122, //!< [8U] convert between YUV YVYU and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_YUY2 = 119, //!< convert between YUV YUY2 and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YUY2 = 120, //!< convert between YUV YUY2 and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_YVYU = 121, //!< convert between YUV YVYU and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YVYU = 122, //!< convert between YUV YVYU and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, //!< synonym to YUY2 COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, //!< synonym to YUY2 COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, //!< synonym to YUY2 COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, //!< synonym to YUY2 - COLOR_YUV2GRAY_UYVY = 123, //!< [8U] extract Y channel from YUV 4:2:2 image - COLOR_YUV2GRAY_YUY2 = 124, //!< [8U] extract Y channel from YUV 4:2:2 image + COLOR_YUV2GRAY_UYVY = 123, //!< extract Y channel from YUV 4:2:2 image + COLOR_YUV2GRAY_YUY2 = 124, //!< extract Y channel from YUV 4:2:2 image //CV_YUV2GRAY_VYUY = CV_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY @@ -734,144 +734,144 @@ enum ColorConversionCodes { COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, //!< synonym to COLOR_YUV2GRAY_YUY2 //! alpha premultiplication - COLOR_RGBA2mRGBA = 125, //!< [8U] - COLOR_mRGBA2RGBA = 126, //!< [8U] + COLOR_RGBA2mRGBA = 125, + COLOR_mRGBA2RGBA = 126, - COLOR_RGB2YUV_I420 = 127, //!< [8U] convert between RGB and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x - COLOR_BGR2YUV_I420 = 128, //!< [8U] convert between BGR and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_I420 = 127, //!< convert between RGB and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_I420 = 128, //!< convert between BGR and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, //!< synonym to I420 COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, //!< synonym to I420 - COLOR_RGBA2YUV_I420 = 129, //!< [8U] convert between RGBA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x - COLOR_BGRA2YUV_I420 = 130, //!< [8U] convert between BGRA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_I420 = 129, //!< convert between RGBA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_I420 = 130, //!< convert between BGRA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, //!< synonym to I420 COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, //!< synonym to I420 - COLOR_RGB2YUV_YV12 = 131, //!< [8U] convert between RGB and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_BGR2YUV_YV12 = 132, //!< [8U] convert between BGR and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_RGBA2YUV_YV12 = 133, //!< [8U] convert between RGBA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x - COLOR_BGRA2YUV_YV12 = 134, //!< [8U] convert between BGRA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_YV12 = 131, //!< convert between RGB and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YV12 = 132, //!< convert between BGR and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YV12 = 133, //!< convert between RGBA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YV12 = 134, //!< convert between BGRA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x //! Demosaicing, see @ref color_convert_bayer "color conversions" for additional information - COLOR_BayerBG2BGR = 46, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2BGR = 47, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2BGR = 48, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2BGR = 49, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR, //!< [8U/16U] - COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR, //!< [8U/16U] - COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR, //!< [8U/16U] - COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR, //!< [8U/16U] - - COLOR_BayerRGGB2RGB = COLOR_BayerBGGR2BGR, //!< [8U/16U] - COLOR_BayerGRBG2RGB = COLOR_BayerGBRG2BGR, //!< [8U/16U] - COLOR_BayerBGGR2RGB = COLOR_BayerRGGB2BGR, //!< [8U/16U] - COLOR_BayerGBRG2RGB = COLOR_BayerGRBG2BGR, //!< [8U/16U] - - COLOR_BayerBG2RGB = COLOR_BayerRG2BGR, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2RGB = COLOR_BayerGR2BGR, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2RGB = COLOR_BayerBG2BGR, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2RGB = COLOR_BayerGB2BGR, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_BayerBG2GRAY = 86, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2GRAY = 87, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2GRAY = 88, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2GRAY = 89, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_BayerRGGB2GRAY = COLOR_BayerBG2GRAY, //!< [8U/16U] - COLOR_BayerGRBG2GRAY = COLOR_BayerGB2GRAY, //!< [8U/16U] - COLOR_BayerBGGR2GRAY = COLOR_BayerRG2GRAY, //!< [8U/16U] - COLOR_BayerGBRG2GRAY = COLOR_BayerGR2GRAY, //!< [8U/16U] + COLOR_BayerBG2BGR = 46, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2BGR = 47, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2BGR = 48, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2BGR = 49, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR, + COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR, + COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR, + COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR, + + COLOR_BayerRGGB2RGB = COLOR_BayerBGGR2BGR, + COLOR_BayerGRBG2RGB = COLOR_BayerGBRG2BGR, + COLOR_BayerBGGR2RGB = COLOR_BayerRGGB2BGR, + COLOR_BayerGBRG2RGB = COLOR_BayerGRBG2BGR, + + COLOR_BayerBG2RGB = COLOR_BayerRG2BGR, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2RGB = COLOR_BayerGR2BGR, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2RGB = COLOR_BayerBG2BGR, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2RGB = COLOR_BayerGB2BGR, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerBG2GRAY = 86, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2GRAY = 87, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2GRAY = 88, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2GRAY = 89, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerRGGB2GRAY = COLOR_BayerBG2GRAY, + COLOR_BayerGRBG2GRAY = COLOR_BayerGB2GRAY, + COLOR_BayerBGGR2GRAY = COLOR_BayerRG2GRAY, + COLOR_BayerGBRG2GRAY = COLOR_BayerGR2GRAY, //! Demosaicing using Variable Number of Gradients - COLOR_BayerBG2BGR_VNG = 62, //!< [8U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2BGR_VNG = 63, //!< [8U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2BGR_VNG = 64, //!< [8U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2BGR_VNG = 65, //!< [8U] equivalent to GBRG Bayer pattern - - COLOR_BayerRGGB2BGR_VNG = COLOR_BayerBG2BGR_VNG, //!< [8U] - COLOR_BayerGRBG2BGR_VNG = COLOR_BayerGB2BGR_VNG, //!< [8U] - COLOR_BayerBGGR2BGR_VNG = COLOR_BayerRG2BGR_VNG, //!< [8U] - COLOR_BayerGBRG2BGR_VNG = COLOR_BayerGR2BGR_VNG, //!< [8U] - - COLOR_BayerRGGB2RGB_VNG = COLOR_BayerBGGR2BGR_VNG, //!< [8U] - COLOR_BayerGRBG2RGB_VNG = COLOR_BayerGBRG2BGR_VNG, //!< [8U] - COLOR_BayerBGGR2RGB_VNG = COLOR_BayerRGGB2BGR_VNG, //!< [8U] - COLOR_BayerGBRG2RGB_VNG = COLOR_BayerGRBG2BGR_VNG, //!< [8U] - - COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG, //!< [8U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG, //!< [8U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG, //!< [8U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG, //!< [8U] equivalent to GBRG Bayer pattern + COLOR_BayerBG2BGR_VNG = 62, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2BGR_VNG = 63, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2BGR_VNG = 64, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2BGR_VNG = 65, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerRGGB2BGR_VNG = COLOR_BayerBG2BGR_VNG, + COLOR_BayerGRBG2BGR_VNG = COLOR_BayerGB2BGR_VNG, + COLOR_BayerBGGR2BGR_VNG = COLOR_BayerRG2BGR_VNG, + COLOR_BayerGBRG2BGR_VNG = COLOR_BayerGR2BGR_VNG, + + COLOR_BayerRGGB2RGB_VNG = COLOR_BayerBGGR2BGR_VNG, + COLOR_BayerGRBG2RGB_VNG = COLOR_BayerGBRG2BGR_VNG, + COLOR_BayerBGGR2RGB_VNG = COLOR_BayerRGGB2BGR_VNG, + COLOR_BayerGBRG2RGB_VNG = COLOR_BayerGRBG2BGR_VNG, + + COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG, //!< equivalent to GBRG Bayer pattern //! Edge-Aware Demosaicing - COLOR_BayerBG2BGR_EA = 135, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2BGR_EA = 136, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2BGR_EA = 137, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2BGR_EA = 138, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_BayerRGGB2BGR_EA = COLOR_BayerBG2BGR_EA, //!< [8U/16U] - COLOR_BayerGRBG2BGR_EA = COLOR_BayerGB2BGR_EA, //!< [8U/16U] - COLOR_BayerBGGR2BGR_EA = COLOR_BayerRG2BGR_EA, //!< [8U/16U] - COLOR_BayerGBRG2BGR_EA = COLOR_BayerGR2BGR_EA, //!< [8U/16U] - - COLOR_BayerRGGB2RGB_EA = COLOR_BayerBGGR2BGR_EA, //!< [8U/16U] - COLOR_BayerGRBG2RGB_EA = COLOR_BayerGBRG2BGR_EA, //!< [8U/16U] - COLOR_BayerBGGR2RGB_EA = COLOR_BayerRGGB2BGR_EA, //!< [8U/16U] - COLOR_BayerGBRG2RGB_EA = COLOR_BayerGRBG2BGR_EA, //!< [8U/16U] - - COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA, //!< [8U/16U] equivalent to GBRG Bayer pattern + COLOR_BayerBG2BGR_EA = 135, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2BGR_EA = 136, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2BGR_EA = 137, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2BGR_EA = 138, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerRGGB2BGR_EA = COLOR_BayerBG2BGR_EA, + COLOR_BayerGRBG2BGR_EA = COLOR_BayerGB2BGR_EA, + COLOR_BayerBGGR2BGR_EA = COLOR_BayerRG2BGR_EA, + COLOR_BayerGBRG2BGR_EA = COLOR_BayerGR2BGR_EA, + + COLOR_BayerRGGB2RGB_EA = COLOR_BayerBGGR2BGR_EA, + COLOR_BayerGRBG2RGB_EA = COLOR_BayerGBRG2BGR_EA, + COLOR_BayerBGGR2RGB_EA = COLOR_BayerRGGB2BGR_EA, + COLOR_BayerGBRG2RGB_EA = COLOR_BayerGRBG2BGR_EA, + + COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA, //!< equivalent to GBRG Bayer pattern //! Demosaicing with alpha channel - COLOR_BayerBG2BGRA = 139, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2BGRA = 140, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2BGRA = 141, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2BGRA = 142, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_BayerRGGB2BGRA = COLOR_BayerBG2BGRA, //!< [8U/16U] - COLOR_BayerGRBG2BGRA = COLOR_BayerGB2BGRA, //!< [8U/16U] - COLOR_BayerBGGR2BGRA = COLOR_BayerRG2BGRA, //!< [8U/16U] - COLOR_BayerGBRG2BGRA = COLOR_BayerGR2BGRA, //!< [8U/16U] - - COLOR_BayerRGGB2RGBA = COLOR_BayerBGGR2BGRA, //!< [8U/16U] - COLOR_BayerGRBG2RGBA = COLOR_BayerGBRG2BGRA, //!< [8U/16U] - COLOR_BayerBGGR2RGBA = COLOR_BayerRGGB2BGRA, //!< [8U/16U] - COLOR_BayerGBRG2RGBA = COLOR_BayerGRBG2BGRA, //!< [8U/16U] - - COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA, //!< [8U/16U] equivalent to RGGB Bayer pattern - COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA, //!< [8U/16U] equivalent to GRBG Bayer pattern - COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, //!< [8U/16U] equivalent to BGGR Bayer pattern - COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, //!< [8U/16U] equivalent to GBRG Bayer pattern - - COLOR_RGB2YUV_UYVY = 143, //!< [8U] convert between RGB and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x - COLOR_BGR2YUV_UYVY = 144, //!< [8U] convert between BGR and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_BayerBG2BGRA = 139, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2BGRA = 140, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2BGRA = 141, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2BGRA = 142, //!< equivalent to GBRG Bayer pattern + + COLOR_BayerRGGB2BGRA = COLOR_BayerBG2BGRA, + COLOR_BayerGRBG2BGRA = COLOR_BayerGB2BGRA, + COLOR_BayerBGGR2BGRA = COLOR_BayerRG2BGRA, + COLOR_BayerGBRG2BGRA = COLOR_BayerGR2BGRA, + + COLOR_BayerRGGB2RGBA = COLOR_BayerBGGR2BGRA, + COLOR_BayerGRBG2RGBA = COLOR_BayerGBRG2BGRA, + COLOR_BayerBGGR2RGBA = COLOR_BayerRGGB2BGRA, + COLOR_BayerGBRG2RGBA = COLOR_BayerGRBG2BGRA, + + COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA, //!< equivalent to RGGB Bayer pattern + COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA, //!< equivalent to GRBG Bayer pattern + COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, //!< equivalent to BGGR Bayer pattern + COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, //!< equivalent to GBRG Bayer pattern + + COLOR_RGB2YUV_UYVY = 143, //!< convert between RGB and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_UYVY = 144, //!< convert between BGR and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x COLOR_RGB2YUV_Y422 = COLOR_RGB2YUV_UYVY, //!< synonym to UYVY COLOR_BGR2YUV_Y422 = COLOR_BGR2YUV_UYVY, //!< synonym to UYVY COLOR_RGB2YUV_UYNV = COLOR_RGB2YUV_UYVY, //!< synonym to UYVY COLOR_BGR2YUV_UYNV = COLOR_BGR2YUV_UYVY, //!< synonym to UYVY - COLOR_RGBA2YUV_UYVY = 145, //!< [8U] convert between RGBA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x - COLOR_BGRA2YUV_UYVY = 146, //!< [8U] convert between BGRA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_UYVY = 145, //!< convert between RGBA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_UYVY = 146, //!< convert between BGRA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x COLOR_RGBA2YUV_Y422 = COLOR_RGBA2YUV_UYVY, //!< synonym to UYVY COLOR_BGRA2YUV_Y422 = COLOR_BGRA2YUV_UYVY, //!< synonym to UYVY COLOR_RGBA2YUV_UYNV = COLOR_RGBA2YUV_UYVY, //!< synonym to UYVY COLOR_BGRA2YUV_UYNV = COLOR_BGRA2YUV_UYVY, //!< synonym to UYVY - COLOR_RGB2YUV_YUY2 = 147, //!< [8U] convert between RGB and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_BGR2YUV_YUY2 = 148, //!< [8U] convert between BGR and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_RGB2YUV_YVYU = 149, //!< [8U] convert between RGB and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x - COLOR_BGR2YUV_YVYU = 150, //!< [8U] convert between BGR and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_YUY2 = 147, //!< convert between RGB and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YUY2 = 148, //!< convert between BGR and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_YVYU = 149, //!< convert between RGB and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YVYU = 150, //!< convert between BGR and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x COLOR_RGB2YUV_YUYV = COLOR_RGB2YUV_YUY2, //!< synonym to YUY2 COLOR_BGR2YUV_YUYV = COLOR_BGR2YUV_YUY2, //!< synonym to YUY2 COLOR_RGB2YUV_YUNV = COLOR_RGB2YUV_YUY2, //!< synonym to YUY2 COLOR_BGR2YUV_YUNV = COLOR_BGR2YUV_YUY2, //!< synonym to YUY2 - COLOR_RGBA2YUV_YUY2 = 151, //!< [8U] convert between RGBA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_BGRA2YUV_YUY2 = 152, //!< [8U] convert between BGRA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x - COLOR_RGBA2YUV_YVYU = 153, //!< [8U] convert between RGBA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x - COLOR_BGRA2YUV_YVYU = 154, //!< [8U] convert between BGRA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YUY2 = 151, //!< convert between RGBA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YUY2 = 152, //!< convert between BGRA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YVYU = 153, //!< convert between RGBA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YVYU = 154, //!< convert between BGRA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2, //!< synonym to YUY2 COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2, //!< synonym to YUY2 COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2, //!< synonym to YUY2 @@ -1071,18 +1071,6 @@ public: //!@brief Returns Size defines the number of tiles in row and column. CV_WRAP virtual Size getTilesGridSize() const = 0; - /** @brief Sets bit shift parameter for histogram bins. - - @param bitShift bit shift value (default is 0). - */ - CV_WRAP virtual void setBitShift(int bitShift) = 0; - - /** @brief Returns the bit shift parameter for histogram bins. - - @return current bit shift value. - */ - CV_WRAP virtual int getBitShift() const = 0; - CV_WRAP virtual void collectGarbage() = 0; }; @@ -1128,27 +1116,13 @@ public: */ CV_WRAP Subdiv2D(Rect rect); - /** @overload */ - CV_WRAP Subdiv2D(Rect2f rect2f); - - /** @overload - - @brief Creates a new empty Delaunay subdivision + /** @brief Creates a new empty Delaunay subdivision @param rect Rectangle that includes all of the 2D points that are to be added to the subdivision. */ CV_WRAP void initDelaunay(Rect rect); - /** @overload - - @brief Creates a new empty Delaunay subdivision - - @param rect Rectangle that includes all of the 2d points that are to be added to the subdivision. - - */ - CV_WRAP_AS(initDelaunay2f) CV_WRAP void initDelaunay(Rect2f rect); - /** @brief Insert a single point into a Delaunay triangulation. @param pt Point to insert. @@ -1498,7 +1472,7 @@ CV_EXPORTS_W void getDerivKernels( OutputArray kx, OutputArray ky, /** @brief Returns Gabor filter coefficients. For more details about gabor filter equations and parameters, see: [Gabor -Filter](https://en.wikipedia.org/wiki/Gabor_filter). +Filter](http://en.wikipedia.org/wiki/Gabor_filter). @param ksize Size of the filter returned. @param sigma Standard deviation of the gaussian envelope. @@ -1580,7 +1554,7 @@ CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, /** @brief Applies the bilateral filter to an image. The function applies bilateral filtering to the input image, as described in -https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html +http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is very slow compared to most filters. @@ -1690,7 +1664,7 @@ stackBlur can generate similar results as Gaussian blur, and the time consumptio It creates a kind of moving stack of colors whilst scanning through the image. Thereby it just has to add one new block of color to the right side of the stack and remove the leftmost color. The remaining colors on the topmost layer of the stack are either added on or reduced by one, depending on if they are on the right or on the left side of the stack. The only supported borderType is BORDER_REPLICATE. -Original paper was proposed by Mario Klingemann, which can be found https://underdestruction.com/2004/02/25/stackblur-2004. +Original paper was proposed by Mario Klingemann, which can be found http://underdestruction.com/2004/02/25/stackblur-2004. @param src input image. The number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S or CV_32F. @@ -1905,7 +1879,7 @@ Check @ref tutorial_canny_detector "the corresponding tutorial" for more details The function finds edges in the input image and marks them in the output map edges using the Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The largest value is used to find initial segments of strong edges. See - + @param image 8-bit input image. @param edges output edge map; single channels 8-bit image, which has the same size as image . @@ -2174,7 +2148,7 @@ An example using the Hough line detector /** @brief Finds lines in a binary image using the standard Hough transform. The function implements the standard or standard multi-scale Hough transform algorithm for line -detection. See for a good explanation of Hough +detection. See for a good explanation of Hough transform. @param image 8-bit, single-channel binary source image. The image may be modified by the function. @@ -3017,15 +2991,15 @@ CV_EXPORTS_W void accumulateWeighted( InputArray src, InputOutputArray dst, The operation takes advantage of the Fourier shift theorem for detecting the translational shift in the frequency domain. It can be used for fast image registration as well as motion estimation. For -more information please see +more information please see Calculates the cross-power spectrum of two supplied source arrays. The arrays are padded if needed with getOptimalDFTSize. The function performs the following equations: -- First it applies a Hanning window to each image to remove possible edge effects, if it's provided -by user. See @ref createHanningWindow and . This window may -be cached until the array size changes to speed up processing time. +- First it applies a Hanning window (see ) to each +image to remove possible edge effects. This window is cached until the array size changes to speed +up processing time. - Next it computes the forward DFTs of each source array: \f[\mathbf{G}_a = \mathcal{F}\{src_1\}, \; \mathbf{G}_b = \mathcal{F}\{src_2\}\f] where \f$\mathcal{F}\f$ is the forward DFT. @@ -3051,25 +3025,9 @@ peak) and will be smaller when there are multiple peaks. CV_EXPORTS_W Point2d phaseCorrelate(InputArray src1, InputArray src2, InputArray window = noArray(), CV_OUT double* response = 0); -/** @brief Detects translational shifts between two images. - -This function extends the standard @ref phaseCorrelate method by improving sub-pixel accuracy -through iterative shift refinement in the phase-correlation space, as described in -@cite hrazdira2020iterative. - -@param src1 Source floating point array (CV_32FC1 or CV_64FC1) -@param src2 Source floating point array (CV_32FC1 or CV_64FC1) -@param L2size The size of the correlation neighborhood used by the iterative shift refinement algorithm. -@param maxIters The maximum number of iterations the iterative refinement algorithm will run. -@returns detected sub-pixel shift between the two arrays. - -@sa phaseCorrelate, dft, idft, createHanningWindow - */ -CV_EXPORTS_W Point2d phaseCorrelateIterative(InputArray src1, InputArray src2, int L2size = 7, int maxIters = 10); - /** @brief This function computes a Hanning window coefficients in two dimensions. -See (https://en.wikipedia.org/wiki/Hann_function) and (https://en.wikipedia.org/wiki/Window_function) +See (http://en.wikipedia.org/wiki/Hann_function) and (http://en.wikipedia.org/wiki/Window_function) for more information. An example is shown below: @@ -3117,10 +3075,9 @@ Also, the special values #THRESH_OTSU or #THRESH_TRIANGLE may be combined with o above values. In these cases, the function determines the optimal threshold value using the Otsu's or Triangle algorithm and uses it instead of the specified thresh. -@note Currently, the Otsu's method is implemented only for CV_8UC1 and CV_16UC1 images, -and the Triangle's method is implemented only for CV_8UC1 images. +@note Currently, the Otsu's and Triangle methods are implemented only for 8-bit single-channel images. -@param src input array (multiple-channel, CV_8U, CV_16S, CV_16U, CV_32F or CV_64F). +@param src input array (multiple-channel, 8-bit or 32-bit floating point). @param dst output array of the same size and type and the same number of channels as src. @param thresh threshold value. @param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding @@ -3128,30 +3085,11 @@ types. @param type thresholding type (see #ThresholdTypes). @return the computed threshold value if Otsu's or Triangle methods used. -@sa thresholdWithMask, adaptiveThreshold, findContours, compare, min, max +@sa adaptiveThreshold, findContours, compare, min, max */ CV_EXPORTS_W double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type ); -/** @brief Same as #threshold, but with an optional mask - -@note If the mask is empty, #thresholdWithMask is equivalent to #threshold. -If the mask is not empty, dst *must* be of the same size and type as src, so that -outliers pixels are left as-is - -@param src input array (multiple-channel, 8-bit or 32-bit floating point). -@param dst output array of the same size and type and the same number of channels as src. -@param mask optional mask (same size as src, 8-bit). -@param thresh threshold value. -@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding -types. -@param type thresholding type (see #ThresholdTypes). -@return the computed threshold value if Otsu's or Triangle methods used. - -@sa threshold, adaptiveThreshold, findContours, compare, min, max -*/ -CV_EXPORTS_W double thresholdWithMask( InputArray src, InputOutputArray dst, InputArray mask, - double thresh, double maxval, int type ); /** @brief Applies an adaptive threshold to an array. @@ -3554,7 +3492,7 @@ An example using the GrabCut algorithm /** @brief Runs the GrabCut algorithm. -The function implements the [GrabCut image segmentation algorithm](https://en.wikipedia.org/wiki/GrabCut). +The function implements the [GrabCut image segmentation algorithm](http://en.wikipedia.org/wiki/GrabCut). @param img Input 8-bit 3-channel image. @param mask Input/output 8-bit single-channel mask. The mask is initialized by the function when @@ -3798,7 +3736,6 @@ floating-point. channels is derived automatically from src and code. @param hint Implementation modfication flags. See #AlgorithmHint -@note The source image (src) must be of an appropriate type for the desired color conversion. see ColorConversionCodes @see @ref imgproc_color_conversions */ CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0, AlgorithmHint hint = cv::ALGO_HINT_DEFAULT ); @@ -3852,7 +3789,6 @@ The function can do the following transformations: #COLOR_BayerBG2BGRA , #COLOR_BayerGB2BGRA , #COLOR_BayerRG2BGRA , #COLOR_BayerGR2BGRA -@note The source image (src) must be of an appropriate type for the desired color conversion. see ColorConversionCodes @sa cvtColor */ CV_EXPORTS_W void demosaicing(InputArray src, OutputArray dst, int code, int dstCn = 0); @@ -3876,18 +3812,6 @@ used for images only. @note Only applicable to contour moments calculations from Python bindings: Note that the numpy type for the input array should be either np.int32 or np.float32. -@note For contour-based moments, the zeroth-order moment \c m00 represents -the contour area. - -If the input contour is degenerate (for example, a single point or all points -are collinear), the area is zero and therefore \c m00 == 0. - -In this case, the centroid coordinates (\c m10/m00, \c m01/m00) are undefined -and must be handled explicitly by the caller. - -A common workaround is to compute the center using cv::boundingRect() or by -averaging the input points. - @sa contourArea, arcLength */ CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); @@ -3895,7 +3819,7 @@ CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); /** @brief Calculates seven Hu invariants. The function calculates seven Hu invariants (introduced in @cite Hu62; see also -) defined as: +) defined as: \f[\begin{array}{l} hu[0]= \eta _{20}+ \eta _{02} \\ hu[1]=( \eta _{20}- \eta _{02})^{2}+4 \eta _{11}^{2} \\ hu[2]=( \eta _{30}-3 \eta _{12})^{2}+ (3 \eta _{21}- \eta _{03})^{2} \\ hu[3]=( \eta _{30}+ \eta _{12})^{2}+ ( \eta _{21}+ \eta _{03})^{2} \\ hu[4]=( \eta _{30}-3 \eta _{12})( \eta _{30}+ \eta _{12})[( \eta _{30}+ \eta _{12})^{2}-3( \eta _{21}+ \eta _{03})^{2}]+(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ hu[5]=( \eta _{20}- \eta _{02})[( \eta _{30}+ \eta _{12})^{2}- ( \eta _{21}+ \eta _{03})^{2}]+4 \eta _{11}( \eta _{30}+ \eta _{12})( \eta _{21}+ \eta _{03}) \\ hu[6]=(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}]-( \eta _{30}-3 \eta _{12})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ \end{array}\f] @@ -3991,7 +3915,7 @@ is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \t of channels as template or only one channel, which is then used for all template and image channels. If the data type is #CV_8U, the mask is interpreted as a binary mask, meaning only elements where mask is nonzero are used and are kept unchanged independent - of the actual mask value (weight equals 1). For data type #CV_32F, the mask values are + of the actual mask value (weight equals 1). For data tpye #CV_32F, the mask values are used as weights. The exact formulas are documented in #TemplateMatchModes. */ CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, @@ -4133,7 +4057,7 @@ CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays con The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less vertices so that the distance between them is less or equal to the specified precision. It uses the -Douglas-Peucker algorithm +Douglas-Peucker algorithm @param curve Input vector of a 2D point stored in std::vector or Mat @param approxCurve Result of the approximation. The type should match the type of the input curve. @@ -4160,7 +4084,7 @@ The algorithm based on the paper @cite LowIlie2003 . @param approxCurve Result of the approximation. The type is vector of a 2D point (Point2f or Point) in std::vector or Mat. @param nsides The parameter defines the number of sides of the result polygon. @param epsilon_percentage defines the percentage of the maximum of additional area. -If it equals -1, it is not used. Otherwise algorithm stops if additional area is greater than contourArea(_curve) * percentage. +If it equals -1, it is not used. Otherwise algorighm stops if additional area is greater than contourArea(_curve) * percentage. If additional area exceeds the limit, algorithm returns as many vertices as there were at the moment the limit was exceeded. @param ensure_convex If it is true, algorithm creates a convex hull of input contour. Otherwise input vector should be convex. */ @@ -4221,11 +4145,7 @@ CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false ); /** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set. The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a -specified point set. The angle of rotation represents the angle between the line connecting the starting -and ending points (based on the clockwise order with greatest index for the corner with greatest \f$y\f$) -and the horizontal axis. This angle always falls between \f$[-90, 0)\f$ because, if the object -rotates more than a rect angle, the next edge is used to measure the angle. The starting and ending points change -as the object rotates.Developer should keep in mind that the returned RotatedRect can contain negative +specified point set. Developer should keep in mind that the returned RotatedRect can contain negative indices when data is close to the containing Mat element boundary. @param points Input vector of 2D points, stored in std::vector\<\> or Mat @@ -4234,12 +4154,9 @@ CV_EXPORTS_W RotatedRect minAreaRect( InputArray points ); /** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle. -The function finds the four vertices of a rotated rectangle. The four vertices are returned -in clockwise order starting from the point with greatest \f$y\f$. If two points have the -same \f$y\f$ coordinate the rightmost is the starting point. This function is useful to draw the +The function finds the four vertices of a rotated rectangle. This function is useful to draw the rectangle. In C++, instead of using this function, you can directly use RotatedRect::points method. Please -visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses -for contours" for more information. +visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses for contours" for more information. @param box The input rotated rectangle. It may be the output of @ref minAreaRect. @param points The output array of four vertices of rectangles. @@ -4281,30 +4198,6 @@ of the OutputArray must be CV_32F. */ CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle ); - -/** -@brief Finds a convex polygon of minimum area enclosing a 2D point set and returns its area. - -This function takes a given set of 2D points and finds the enclosing polygon with k vertices and minimal -area. It takes the set of points and the parameter k as input and returns the area of the minimal -enclosing polygon. - -The Implementation is based on a paper by Aggarwal, Chang and Yap @cite Aggarwal1985. They -provide a \f$\theta(n²log(n)log(k))\f$ algorithm for finding the minimal convex polygon with k -vertices enclosing a 2D convex polygon with n vertices (k < n). Since the #minEnclosingConvexPolygon -function takes a 2D point set as input, an additional preprocessing step of computing the convex hull -of the 2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which -is lower than \f$\theta(n²log(n)log(k))\f$. Thus the overall complexity of the function is -\f$O(n²log(n)log(k))\f$. - -@param points Input vector of 2D points, stored in std::vector\<\> or Mat -@param polygon Output vector of 2D points defining the vertices of the enclosing polygon -@param k Number of vertices of the output polygon - */ - -CV_EXPORTS_W double minEnclosingConvexPolygon ( InputArray points, OutputArray polygon, int k ); - - /** @brief Compares two shapes. The function compares two shapes. All three implemented methods use the Hu invariants (see #HuMoments) @@ -4412,9 +4305,6 @@ ellipse/rotatedRect data contains negative indices, due to the data points being border of the containing Mat element. @param points Input 2D point set, stored in std::vector\<\> or Mat - -@note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. -@note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipse( InputArray points ); @@ -4452,9 +4342,6 @@ CV_EXPORTS_W RotatedRect fitEllipse( InputArray points ); \f} @param points Input 2D point set, stored in std::vector\<\> or Mat - - @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. - @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points ); @@ -4500,26 +4387,9 @@ CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points ); The scaling factor guarantees that \f$A^T C A =1\f$. @param points Input 2D point set, stored in std::vector\<\> or Mat - - @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required. - @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error. */ CV_EXPORTS_W RotatedRect fitEllipseDirect( InputArray points ); -/** @brief Compute for each 2d point the nearest 2d point located on a given ellipse. - - The function computes the nearest 2d location on a given ellipse for a vector of 2d points and is based on @cite Chatfield2017 code. - This function can be used to compute for instance the ellipse fitting error. - - @param ellipse_params Ellipse parameters - @param points Input 2d points - @param closest_pts For each 2d point, their corresponding closest 2d point located on a given ellipse - - @note Input point types are @ref Point2i or @ref Point2f - @see fitEllipse, fitEllipseAMS, fitEllipseDirect - */ -CV_EXPORTS_W void getClosestEllipsePoints( const RotatedRect& ellipse_params, InputArray points, OutputArray closest_pts ); - /** @brief Fits a line to a 2D or 3D point set. The function fitLine fits a line to a 2D or 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where @@ -4538,7 +4408,7 @@ of the following: - DIST_HUBER \f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] -The algorithm is based on the M-estimator ( ) technique +The algorithm is based on the M-estimator ( ) technique that iteratively fits the line using the weighted least-squares algorithm. After each iteration the weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . @@ -4986,11 +4856,6 @@ The function cv::putText renders the specified text string in the image. Symbols using the specified font are replaced by question marks. See #getTextSize for a text rendering code example. -The `fontScale` parameter is a scale factor that is multiplied by the base font size: -- When scale > 1, the text is magnified. -- When 0 < scale < 1, the text is minimized. -- When scale < 0, the text is mirrored or reversed. - @param img Image. @param text Text string to be drawn. @param org Bottom-left corner of the text string in the image. diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/bindings.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/bindings.hpp index ad507a5bf9d48f1d9dc22d770bcb7d131e7640fd..c69527a779452455f31dc0ce20cfe53587f4419e 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/bindings.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/bindings.hpp @@ -21,34 +21,14 @@ void HoughLinesWithAccumulator( InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, - double min_theta = 0, double max_theta = CV_PI, - bool use_edgeval = false + double min_theta = 0, double max_theta = CV_PI ) { std::vector lines_acc; - HoughLines(image, lines_acc, rho, theta, threshold, srn, stn, min_theta, max_theta, use_edgeval); + HoughLines(image, lines_acc, rho, theta, threshold, srn, stn, min_theta, max_theta); Mat(lines_acc).copyTo(lines); } -/** @brief Finds circles in a grayscale image using the Hough transform and get accumulator. - * - * @note This function is for bindings use only. Use original function in C++ code - * - * @sa HoughCircles - */ -CV_WRAP static inline -void HoughCirclesWithAccumulator( - InputArray image, OutputArray circles, - int method, double dp, double minDist, - double param1 = 100, double param2 = 100, - int minRadius = 0, int maxRadius = 0 -) -{ - std::vector circles_acc; - HoughCircles(image, circles_acc, method, dp, minDist, param1, param2, minRadius, maxRadius); - Mat(1, static_cast(circles_acc.size()), CV_32FC4, &circles_acc.front()).copyTo(circles); -} - } // namespace #endif // OPENCV_IMGPROC_BINDINGS_HPP diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h new file mode 100644 index 0000000000000000000000000000000000000000..3d7b650d587dee8b0705b76b8115d73e697b0312 --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_filter_and_csc.h @@ -0,0 +1,16 @@ +// +// Created by hf on 25-9-18. +// + +#ifndef OPENCV_CUST_FILTER_AND_CSC_H +#define OPENCV_CUST_FILTER_AND_CSC_H + + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { +CV_EXPORTS void filter_and_csc(InputArray &src, OutputArray &dst); + +} +#endif // OPENCV_CUST_FILTER_AND_CSC_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h new file mode 100644 index 0000000000000000000000000000000000000000..003cc123f7d106403dc0d45342916f87dd37a3de --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_mag_and_ang.h @@ -0,0 +1,15 @@ +// +// Created by hf on 25-9-18. +// + +#ifndef OPENCV_CUST_MAG_AND_ANG_H +#define OPENCV_CUST_MAG_AND_ANG_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { +CV_EXPORTS void mag_and_ang(InputArray src,OutputArray dst_mag,OutputArray dst_ang); + +} +#endif // OPENCV_CUST_MAG_AND_ANG_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_ncc.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_ncc.h new file mode 100644 index 0000000000000000000000000000000000000000..7c426214cf6d0a360af0b269ad1643eccad088bb --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_ncc.h @@ -0,0 +1,16 @@ +// +// Created by hf on 25-9-15. +// + +#ifndef OPENCV_CUST_NCC_H +#define OPENCV_CUST_NCC_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void ncc(cv::Mat& src1_input,cv::Mat& src2_input,// + double& number,double& sum1,double& sum2); +} + +#endif // OPENCV_CUST_NCC_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_s16.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_s16.h new file mode 100644 index 0000000000000000000000000000000000000000..9d30436cc283c3fc59595b118e844ce5489fb0dd --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_s16.h @@ -0,0 +1,16 @@ +// +// Created by hf on 25-9-15. +// + +#ifndef OPENCV_CUST_THRESHOLD_S16_H +#define OPENCV_CUST_THRESHOLD_S16_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void threshold_s16(cv::Mat& input, cv::Mat& output, + double MIN_VAL, double MAX_VAL); +} + +#endif // OPENCV_CUST_THRESHOLD_S16_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_u16.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_u16.h new file mode 100644 index 0000000000000000000000000000000000000000..7e2fc541cb3fa0b12e9ebfe3bba86ed9227e46bf --- /dev/null +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/cust_threshold_u16.h @@ -0,0 +1,16 @@ +// +// Created by hf on 25-9-15. +// + +#ifndef OPENCV_CUST_THRESHOLD_U16_H +#define OPENCV_CUST_THRESHOLD_U16_H + +#include "opencv2/core.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv{ +CV_EXPORTS void threshold_u16(cv::Mat& input, cv::Mat& output, + double MIN_VAL, double MAX_VAL); +} + +#endif // OPENCV_CUST_THRESHOLD_U16_H diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/types_c.h b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/types_c.h index 14a0ec796bbe81b53d012be81efd91a20b8eaecf..255ed0c37f65a73de494e06e4c65c216e6593486 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/types_c.h +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/imgproc/types_c.h @@ -389,7 +389,6 @@ enum MorphShapes_c CV_SHAPE_RECT =0, CV_SHAPE_CROSS =1, CV_SHAPE_ELLIPSE =2, - CV_SHAPE_DIAMOND =3, CV_SHAPE_CUSTOM =100 //!< custom structuring element }; @@ -611,11 +610,9 @@ enum CV_THRESH_MASK =7, CV_THRESH_OTSU =8, /**< use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */ - CV_THRESH_TRIANGLE =16, /**< use Triangle algorithm to choose the optimal threshold value; + CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values, but not with CV_THRESH_OTSU */ - CV_THRESH_DRYRUN =128 /**< compute threshold only (useful for OTSU/TRIANGLE) but does not - actually run thresholding */ }; /** Adaptive threshold methods */ diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/ml.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/ml.hpp index b66a300402863d308ff1508235302359b5a6e285..d537ab7759b6888994fe7793b652ee310c675b51 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/ml.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/ml.hpp @@ -256,7 +256,7 @@ public: @param filename The input file name @param headerLineCount The number of lines in the beginning to skip; besides the header, the - function also skips empty lines and lines starting with `#` + function also skips empty lines and lines staring with `#` @param responseStartIdx Index of the first output variable. If -1, the function considers the last variable as the response @param responseEndIdx Index of the last output variable + 1. If -1, then there is single diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect.hpp index 4a8544b9104fc75917f2ff17f28b127db0d0b1df..7f1189060806121c049ff6453a698a77cd29e2df 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect.hpp @@ -729,8 +729,7 @@ public: }; enum ECIEncodings { - ECI_SHIFT_JIS = 20, - ECI_UTF8 = 26, + ECI_UTF8 = 26 }; /** @brief QR code encoder parameters. */ @@ -742,10 +741,10 @@ public: CV_PROP_RW int version; //! The optional level of error correction (by default - the lowest). - CV_PROP_RW QRCodeEncoder::CorrectionLevel correction_level; + CV_PROP_RW CorrectionLevel correction_level; //! The optional encoding mode - Numeric, Alphanumeric, Byte, Kanji, ECI or Structured Append. - CV_PROP_RW QRCodeEncoder::EncodeMode mode; + CV_PROP_RW EncodeMode mode; //! The optional number of QR codes to generate in Structured Append mode. CV_PROP_RW int structure_number; @@ -809,13 +808,6 @@ public: */ CV_WRAP std::string detectAndDecodeCurved(InputArray img, OutputArray points=noArray(), OutputArray straight_qrcode = noArray()); - - /** @brief Returns a kind of encoding for the decoded info from the latest @ref decode or @ref detectAndDecode call - @param codeIdx an index of the previously decoded QR code. - When @ref decode or @ref detectAndDecode is used, valid value is zero. - For @ref decodeMulti or @ref detectAndDecodeMulti use indices corresponding to the output order. - */ - CV_WRAP QRCodeEncoder::ECIEncodings getEncoding(int codeIdx = 0); }; class CV_EXPORTS_W_SIMPLE QRCodeDetectorAruco : public GraphicalCodeDetector { diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_detector.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_detector.hpp index c6ae25b71875c948c1595a9dfb8b6846504931e6..9d30d55d176e44eae05d26e3e66053284451b8c2 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_detector.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_detector.hpp @@ -285,16 +285,6 @@ public: const DetectorParameters &detectorParams = DetectorParameters(), const RefineParameters& refineParams = RefineParameters()); - /** @brief ArucoDetector constructor for multiple dictionaries - * - * @param dictionaries indicates the type of markers that will be searched. Empty dictionaries will throw an error. - * @param detectorParams marker detection parameters - * @param refineParams marker refine detection parameters - */ - CV_WRAP ArucoDetector(const std::vector &dictionaries, - const DetectorParameters &detectorParams = DetectorParameters(), - const RefineParameters& refineParams = RefineParameters()); - /** @brief Basic marker detection * * @param image input image @@ -307,7 +297,7 @@ public: * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a * correct codification. Useful for debugging purposes. * - * Performs marker detection in the input image. Only markers included in the first specified dictionary + * Performs marker detection in the input image. Only markers included in the specific dictionary * are searched. For each detected marker, it returns the 2D position of its corner in the image * and its corresponding identifier. * Note that this function does not perform pose estimation. @@ -318,33 +308,6 @@ public: CV_WRAP void detectMarkers(InputArray image, OutputArrayOfArrays corners, OutputArray ids, OutputArrayOfArrays rejectedImgPoints = noArray()) const; - /** @brief Marker detection with confidence computation - * - * @param image input image - * @param corners vector of detected marker corners. For each marker, its four corners - * are provided, (e.g std::vector > ). For N detected markers, - * the dimensions of this array is Nx4. The order of the corners is clockwise. - * @param ids vector of identifiers of the detected markers. The identifier is of type int - * (e.g. std::vector). For N detected markers, the size of ids is also N. - * The identifiers have the same order than the markers in the imgPoints array. - * @param markersConfidence contains the normalized confidence [0;1] of the markers' detection, - * defined as 1 minus the normalized uncertainty (percentage of incorrect pixel detections), - * with 1 describing a pixel perfect detection. The confidence values are of type float - * (e.g. std::vector) - * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a - * correct codification. Useful for debugging purposes. - * - * Performs marker detection in the input image. Only markers included in the first specified dictionary - * are searched. For each detected marker, it returns the 2D position of its corner in the image - * and its corresponding identifier. - * Note that this function does not perform pose estimation. - * @note The function does not correct lens distortion or takes it into account. It's recommended to undistort - * input image with corresponding camera model, if camera parameters are known - * @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard - */ - CV_WRAP void detectMarkersWithConfidence(InputArray image, OutputArrayOfArrays corners, OutputArray ids, OutputArray markersConfidence, - OutputArrayOfArrays rejectedImgPoints = noArray()) const; - /** @brief Refine not detected markers based on the already detected and the board layout * * @param image input image @@ -366,8 +329,6 @@ public: * If camera parameters and distortion coefficients are provided, missing markers are reprojected * using projectPoint function. If not, missing marker projections are interpolated using global * homography, and all the marker corners in the board must have the same Z coordinate. - * @note This function assumes that the board only contains markers from one dictionary, so only the - * first configured dictionary is used. It has to match the dictionary of the board to work properly. */ CV_WRAP void refineDetectedMarkers(InputArray image, const Board &board, InputOutputArrayOfArrays detectedCorners, @@ -375,59 +336,9 @@ public: InputArray cameraMatrix = noArray(), InputArray distCoeffs = noArray(), OutputArray recoveredIdxs = noArray()) const; - /** @brief Basic marker detection - * - * @param image input image - * @param corners vector of detected marker corners. For each marker, its four corners - * are provided, (e.g std::vector > ). For N detected markers, - * the dimensions of this array is Nx4. The order of the corners is clockwise. - * @param ids vector of identifiers of the detected markers. The identifier is of type int - * (e.g. std::vector). For N detected markers, the size of ids is also N. - * The identifiers have the same order than the markers in the imgPoints array. - * @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a - * correct codification. Useful for debugging purposes. - * @param dictIndices vector of dictionary indices for each detected marker. Use getDictionaries() to get the - * list of corresponding dictionaries. - * - * Performs marker detection in the input image. Only markers included in the specific dictionaries - * are searched. For each detected marker, it returns the 2D position of its corner in the image - * and its corresponding identifier. - * Note that this function does not perform pose estimation. - * @note The function does not correct lens distortion or takes it into account. It's recommended to undistort - * input image with corresponding camera model, if camera parameters are known - * @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard - */ - CV_WRAP void detectMarkersMultiDict(InputArray image, OutputArrayOfArrays corners, OutputArray ids, - OutputArrayOfArrays rejectedImgPoints = noArray(), OutputArray dictIndices = noArray()) const; - - /** @brief Returns first dictionary from internal list used for marker detection. - * - * @return The first dictionary from the configured ArucoDetector. - */ CV_WRAP const Dictionary& getDictionary() const; - - /** @brief Sets and replaces the first dictionary in internal list to be used for marker detection. - * - * @param dictionary The new dictionary that will replace the first dictionary in the internal list. - */ CV_WRAP void setDictionary(const Dictionary& dictionary); - /** @brief Returns all dictionaries currently used for marker detection as a vector. - * - * @return A std::vector containing all dictionaries used by the ArucoDetector. - */ - CV_WRAP std::vector getDictionaries() const; - - /** @brief Sets the entire collection of dictionaries to be used for marker detection, replacing any existing dictionaries. - * - * @param dictionaries A std::vector containing the new set of dictionaries to be used. - * - * Configures the ArucoDetector to use the provided vector of dictionaries for marker detection. - * This method replaces any dictionaries that were previously set. - * @note Setting an empty vector of dictionaries will throw an error. - */ - CV_WRAP void setDictionaries(const std::vector& dictionaries); - CV_WRAP const DetectorParameters& getDetectorParameters() const; CV_WRAP void setDetectorParameters(const DetectorParameters& detectorParameters); diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_dictionary.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_dictionary.hpp index 6a90876bf9546cf50b3538bdde40f573140710ef..bc7b934b2a608d22782a56d84d01c874e9a19995 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_dictionary.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/aruco_dictionary.hpp @@ -71,6 +71,7 @@ class CV_EXPORTS_W_SIMPLE Dictionary { */ CV_WRAP int getDistanceToId(InputArray bits, int id, bool allRotations = true) const; + /** @brief Generate a canonical marker image */ CV_WRAP void generateImageMarker(int id, int sidePixels, OutputArray _img, int borderBits = 1) const; @@ -83,7 +84,7 @@ class CV_EXPORTS_W_SIMPLE Dictionary { /** @brief Transform list of bytes to matrix of bits */ - CV_WRAP static Mat getBitsFromByteList(const Mat &byteList, int markerSize, int rotationId = 0); + CV_WRAP static Mat getBitsFromByteList(const Mat &byteList, int markerSize); }; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/charuco_detector.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/charuco_detector.hpp index 999874c12e4bbac6e04df64a12298dae270da558..e10cb3f0254220f51208d76a4bdc5ee251a0504f 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/charuco_detector.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/charuco_detector.hpp @@ -16,7 +16,6 @@ struct CV_EXPORTS_W_SIMPLE CharucoParameters { CV_WRAP CharucoParameters() { minMarkers = 2; tryRefineMarkers = false; - checkMarkers = true; } /// cameraMatrix optional 3x3 floating-point camera matrix CV_PROP_RW Mat cameraMatrix; @@ -29,9 +28,6 @@ struct CV_EXPORTS_W_SIMPLE CharucoParameters { /// try to use refine board, default false CV_PROP_RW bool tryRefineMarkers; - - /// run check to verify that markers belong to the same board, default true - CV_PROP_RW bool checkMarkers; }; class CV_EXPORTS_W CharucoDetector : public Algorithm { @@ -62,7 +58,7 @@ public: /** * @brief detect aruco markers and interpolate position of ChArUco board corners - * @param image input image necessary for corner refinement. Note that markers are not detected and + * @param image input image necesary for corner refinement. Note that markers are not detected and * should be sent in corners and ids parameters. * @param charucoCorners interpolated chessboard corners. * @param charucoIds interpolated chessboard corners identifiers. diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp index adc52379b9030978fd4118967a45b94e7ead46e7..ed697c50c0556b615d0e078ba1ee3cb0803078e5 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/objdetect/graphical_code_detector.hpp @@ -73,17 +73,6 @@ public: */ CV_WRAP bool detectAndDecodeMulti(InputArray img, CV_OUT std::vector& decoded_info, OutputArray points = noArray(), OutputArrayOfArrays straight_code = noArray()) const; - -#ifdef OPENCV_BINDINGS_PARSER - CV_WRAP_AS(detectAndDecodeBytes) NativeByteArray detectAndDecode(InputArray img, OutputArray points = noArray(), - OutputArray straight_code = noArray()) const; - CV_WRAP_AS(decodeBytes) NativeByteArray decode(InputArray img, InputArray points, OutputArray straight_code = noArray()) const; - CV_WRAP_AS(decodeBytesMulti) bool decodeMulti(InputArray img, InputArray points, CV_OUT std::vector& decoded_info, - OutputArrayOfArrays straight_code = noArray()) const; - CV_WRAP_AS(detectAndDecodeBytesMulti) bool detectAndDecodeMulti(InputArray img, CV_OUT std::vector& decoded_info, OutputArray points = noArray(), - OutputArrayOfArrays straight_code = noArray()) const; -#endif - struct Impl; protected: Ptr p; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/opencv_modules.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/opencv_modules.hpp index c9e24d845febeb7d63c0352609e0acf2278274be..6e93caa02020c38b07a390e38f63f20d8a68bbad 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/opencv_modules.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/opencv_modules.hpp @@ -25,6 +25,5 @@ #define HAVE_OPENCV_STITCHING #define HAVE_OPENCV_VIDEO #define HAVE_OPENCV_VIDEOIO -#define HAVE_OPENCV_WORLD diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/exposure_compensate.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/exposure_compensate.hpp index 2954f32ca36fa7ca382aa232e1fb6630f087534b..dea76c957bd79edac410a9ce29281404a1c0cbe0 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/exposure_compensate.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/exposure_compensate.hpp @@ -187,7 +187,7 @@ public: protected: template - void feedWithStrategy(const std::vector &corners, const std::vector &images, + void feed(const std::vector &corners, const std::vector &images, const std::vector > &masks); private: diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/seam_finders.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/seam_finders.hpp index bae7aa0135063ac18daefaf3a026feca4950f869..9ccfd144247111947b41e5040c4ad13e0ce3ff08 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/seam_finders.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/stitching/detail/seam_finders.hpp @@ -235,7 +235,7 @@ public: enum CostType { COST_COLOR, COST_COLOR_GRAD }; }; -/** @brief Minimum graph cut-based seam estimator. See details in @cite Kwatra03 . +/** @brief Minimum graph cut-based seam estimator. See details in @cite V03 . */ class CV_EXPORTS_W GraphCutSeamFinder : public GraphCutSeamFinderBase, public SeamFinder { diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/background_segm.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/background_segm.hpp index 2d3ea823b3c98fe8763153740367010c4d201cdc..e1dfa15a9a554aceee71d3a935b11201b9326b9f 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/background_segm.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/background_segm.hpp @@ -71,21 +71,6 @@ public: */ CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) = 0; - /** @brief Computes a foreground mask with known foreground mask input. - - @param image Next video frame. Floating point frame will be used without scaling and should be in range \f$[0,255]\f$. - @param fgmask The output foreground mask as an 8-bit binary image. - @param knownForegroundMask The mask for inputting already known foreground, allows model to ignore pixels. - @param learningRate The value between 0 and 1 that indicates how fast the background model is - learnt. Negative parameter value makes the algorithm to use some automatically chosen learning - rate. 0 means that the background model is not updated at all, 1 means that the background model - is completely reinitialized from the last frame. - - @note This method has a default virtual implementation that throws a "not impemented" error. - Foreground masking may not be supported by all background subtractors. - */ - CV_WRAP virtual void apply(InputArray image, InputArray knownForegroundMask, OutputArray fgmask, double learningRate=-1) = 0; - /** @brief Computes a background image. @param backgroundImage The output background image. @@ -117,7 +102,7 @@ public: CV_WRAP virtual int getNMixtures() const = 0; /** @brief Sets the number of gaussian components in the background model. - The model needs to be reinitialized to reserve memory. + The model needs to be reinitalized to reserve memory. */ CV_WRAP virtual void setNMixtures(int nmixtures) = 0;//needs reinitialization! @@ -221,18 +206,6 @@ public: is completely reinitialized from the last frame. */ CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) CV_OVERRIDE = 0; - - /** @brief Computes a foreground mask and skips known foreground in evaluation. - - @param image Next video frame. Floating point frame will be used without scaling and should be in range \f$[0,255]\f$. - @param fgmask The output foreground mask as an 8-bit binary image. - @param knownForegroundMask The mask for inputting already known foreground, allows model to ignore pixels. - @param learningRate The value between 0 and 1 that indicates how fast the background model is - learnt. Negative parameter value makes the algorithm to use some automatically chosen learning - rate. 0 means that the background model is not updated at all, 1 means that the background model - is completely reinitialized from the last frame. - */ - CV_WRAP virtual void apply(InputArray image, InputArray knownForegroundMask, OutputArray fgmask, double learningRate=-1) CV_OVERRIDE = 0; }; /** @brief Creates MOG2 Background Subtractor @@ -268,7 +241,7 @@ public: CV_WRAP virtual int getNSamples() const = 0; /** @brief Sets the number of data samples in the background model. - The model needs to be reinitialized to reserve memory. + The model needs to be reinitalized to reserve memory. */ CV_WRAP virtual void setNSamples(int _nN) = 0;//needs reinitialization! diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/tracking.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/tracking.hpp index 2ed27f505d514c8b15dd8923dd92977b4a549b74..ac3788772a3680c003c020c01bc323bb26bacc7a 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/tracking.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/video/tracking.hpp @@ -46,9 +46,6 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" -#ifdef HAVE_OPENCV_DNN -# include "opencv2/dnn.hpp" -#endif namespace cv { @@ -268,43 +265,17 @@ enum MOTION_HOMOGRAPHY = 3 }; -/** -@brief Computes the Enhanced Correlation Coefficient (ECC) value between two images - -The Enhanced Correlation Coefficient (ECC) is a normalized measure of similarity between two images @cite EP08. -The result lies in the range [-1, 1], where 1 corresponds to perfect similarity (modulo affine shift and scale), -0 indicates no correlation, and -1 indicates perfect negative correlation. - -For single-channel images, the ECC is defined as: - -\f[ -\mathrm{ECC}(I, T) = \frac{\sum_{x} (I(x) - \mu_I)(T(x) - \mu_T)} -{\sqrt{\sum_{x} (I(x) - \mu_I)^2} \cdot \sqrt{\sum_{x} (T(x) - \mu_T)^2}} -\f] - -For multi-channel images (e.g., 3-channel RGB), the formula generalizes to: - -\f[ -\mathrm{ECC}(I, T) = -\frac{\sum_{x} \sum_{c=1}^{C} (I_c(x) - \mu_{I_c})(T_c(x) - \mu_{T_c})} -{\sqrt{\sum_{x} \sum_{c=1}^{C} (I_c(x) - \mu_{I_c})^2} \cdot - \sqrt{\sum_{x} \sum_{c=1}^{C} (T_c(x) - \mu_{T_c})^2}} -\f] +/** @brief Computes the Enhanced Correlation Coefficient value between two images @cite EP08 . -Where: -- \f$I_c(x), T_c(x)\f$ are the values of channel \f$c\f$ at spatial location \f$x\f$, -- \f$\mu_{I_c}, \mu_{T_c}\f$ are the mean values of channel \f$c\f$ over the masked region (if provided), -- \f$C\f$ is the number of channels (only 1 and 3 are currently supported), -- The sums run over all pixels \f$x\f$ in the image domain (optionally restricted by mask). +@param templateImage single-channel template image; CV_8U or CV_32F array. +@param inputImage single-channel input image to be warped to provide an image similar to + templateImage, same type as templateImage. +@param inputMask An optional mask to indicate valid values of inputImage. -@param templateImage Input template image; must have either 1 or 3 channels and be of type CV_8U, CV_16U, CV_32F, or CV_64F. -@param inputImage Input image to be compared with the template; must have the same type and number of channels as templateImage. -@param inputMask Optional single-channel mask to specify the valid region of interest in inputImage and templateImage. - -@return The ECC similarity coefficient in the range [-1, 1]. +@sa +findTransformECC + */ -@sa findTransformECC -*/ CV_EXPORTS_W double computeECC(InputArray templateImage, InputArray inputImage, InputArray inputMask = noArray()); /** @example samples/cpp/image_alignment.cpp @@ -313,8 +284,8 @@ An example using the image alignment ECC algorithm /** @brief Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 . -@param templateImage 1 or 3 channel template image; CV_8U, CV_16U, CV_32F, CV_64F type. -@param inputImage input image which should be warped with the final warpMatrix in +@param templateImage single-channel template image; CV_8U or CV_32F array. +@param inputImage single-channel input image which should be warped with the final warpMatrix in order to provide an image similar to templateImage, same type as templateImage. @param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp). @param motionType parameter, specifying the type of motion: @@ -331,7 +302,7 @@ order to provide an image similar to templateImage, same type as templateImage. criteria.epsilon defines the threshold of the increment in the correlation coefficient between two iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion). Default values are shown in the declaration above. -@param inputMask An optional single channel mask to indicate valid values of inputImage. +@param inputMask An optional mask to indicate valid values of inputImage. @param gaussFiltSize An optional value indicating size of gaussian blur filter; (DEFAULT: 5) The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion @@ -374,51 +345,6 @@ double findTransformECC(InputArray templateImage, InputArray inputImage, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001), InputArray inputMask = noArray()); -/** @brief Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 -using validity masks for both the template and the input images. - -This function extends findTransformECC() by adding a mask for the template image. -The Enhanced Correlation Coefficient is evaluated only over pixels that are valid in both images: -on each iteration inputMask is warped into the template frame and combined with templateMask, and -only the intersection of these masks contributes to the objective function. - -@param templateImage 1 or 3 channel template image; CV_8U, CV_16U, CV_32F, CV_64F type. -@param inputImage input image which should be warped with the final warpMatrix in -order to provide an image similar to templateImage, same type as templateImage. -@param templateMask single-channel 8-bit mask for templateImage indicating valid pixels -to be used in the alignment. Must have the same size as templateImage. -@param inputMask single-channel 8-bit mask for inputImage indicating valid pixels -before warping. Must have the same size as inputImage. -@param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp). -@param motionType parameter, specifying the type of motion: - - **MOTION_TRANSLATION** sets a translational motion model; warpMatrix is \f$2\times 3\f$ with - the first \f$2\times 2\f$ part being the unity matrix and the rest two parameters being - estimated. - - **MOTION_EUCLIDEAN** sets a Euclidean (rigid) transformation as motion model; three - parameters are estimated; warpMatrix is \f$2\times 3\f$. - - **MOTION_AFFINE** sets an affine motion model (DEFAULT); six parameters are estimated; - warpMatrix is \f$2\times 3\f$. - - **MOTION_HOMOGRAPHY** sets a homography as a motion model; eight parameters are - estimated; warpMatrix is \f$3\times 3\f$. -@param criteria parameter, specifying the termination criteria of the ECC algorithm; -criteria.epsilon defines the threshold of the increment in the correlation coefficient between two -iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion). -Default values are shown in the declaration above. -@param gaussFiltSize size of the Gaussian blur filter used for smoothing images and masks -before computing the alignment (DEFAULT: 5). - -@sa -findTransformECC, computeECC, estimateAffine2D, estimateAffinePartial2D, findHomography -*/ -CV_EXPORTS_W double findTransformECCWithMask( InputArray templateImage, - InputArray inputImage, - InputArray templateMask, - InputArray inputMask, - InputOutputArray warpMatrix, - int motionType = MOTION_AFFINE, - TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 50, 1e-6), - int gaussFiltSize = 5 ); - /** @example samples/cpp/kalman.cpp An example using the standard Kalman filter */ @@ -678,16 +604,6 @@ public: /** @copybrief getFinestScale @see getFinestScale */ CV_WRAP virtual void setFinestScale(int val) = 0; - /** @brief Sets the coarsest scale - @param val Coarsest level of the Gaussian pyramid on which the flow is computed. - If set to -1, the auto-computed coarsest scale will be used. - */ - CV_WRAP virtual void setCoarsestScale(int val) = 0; - - /** @brief Gets the coarsest scale - */ - CV_WRAP virtual int getCoarsestScale() const = 0; - /** @brief Size of an image patch for matching (in pixels). Normally, default 8x8 patches work well enough in most cases. @see setPatchSize */ @@ -910,13 +826,6 @@ public: static CV_WRAP Ptr create(const TrackerGOTURN::Params& parameters = TrackerGOTURN::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - @param model pre-loaded GOTURN model - */ - static CV_WRAP Ptr create(const dnn::Net& model); -#endif - //void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE; //bool update(InputArray image, CV_OUT Rect& boundingBox) CV_OVERRIDE; }; @@ -944,16 +853,6 @@ public: static CV_WRAP Ptr create(const TrackerDaSiamRPN::Params& parameters = TrackerDaSiamRPN::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param siam_rpn pre-loaded SiamRPN model - * @param kernel_cls1 pre-loaded CLS model - * @param kernel_r1 pre-loaded R1 model - */ - static CV_WRAP - Ptr create(const dnn::Net& siam_rpn, const dnn::Net& kernel_cls1, const dnn::Net& kernel_r1); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; @@ -992,15 +891,6 @@ public: static CV_WRAP Ptr create(const TrackerNano::Params& parameters = TrackerNano::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param backbone pre-loaded backbone model - * @param neckhead pre-loaded neckhead model - */ - static CV_WRAP - Ptr create(const dnn::Net& backbone, const dnn::Net& neckhead); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; @@ -1039,18 +929,6 @@ public: static CV_WRAP Ptr create(const TrackerVit::Params& parameters = TrackerVit::Params()); -#ifdef HAVE_OPENCV_DNN - /** @brief Constructor - * @param model pre-loaded DNN model - * @param meanvalue mean value for image preprocessing - * @param stdvalue std value for image preprocessing - * @param tracking_score_threshold threshold for tracking score - */ - static CV_WRAP - Ptr create(const dnn::Net& model, Scalar meanvalue = Scalar(0.485, 0.456, 0.406), - Scalar stdvalue = Scalar(0.229, 0.224, 0.225), float tracking_score_threshold = 0.20f); -#endif - /** @brief Return tracking score */ CV_WRAP virtual float getTrackingScore() = 0; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/videoio.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/videoio.hpp index 7688718c47cc768311ca96b876e3cecd423c6bf3..6e50f87e44c13067bd002df995302d20d86fd941 100644 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/videoio.hpp +++ b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/videoio.hpp @@ -128,7 +128,7 @@ enum VideoCaptureAPIs { CAP_INTEL_MFX = 2300, //!< Intel MediaSDK CAP_XINE = 2400, //!< XINE engine (Linux) CAP_UEYE = 2500, //!< uEye Camera API - CAP_OBSENSOR = 2600, //!< For Orbbec 3D-Sensor device/module (Astra+, Femto, Astra2, Gemini2, Gemini2L, Gemini2XL, Gemini330, Femto Mega) attention: Astra2 cameras currently only support Windows and Linux kernel versions no higher than 4.15, and higher versions of Linux kernel may have exceptions. + CAP_OBSENSOR = 2600, //!< For Orbbec 3D-Sensor device/module (Astra+, Femto, Astra2, Gemini2, Gemini2L, Gemini2XL, Femto Mega) attention: Astra2 cameras currently only support Windows and Linux kernel versions no higher than 4.15, and higher versions of Linux kernel may have exceptions. }; @@ -156,7 +156,7 @@ enum VideoCaptureProperties { CAP_PROP_HUE =13, //!< Hue of the image (only for cameras). CAP_PROP_GAIN =14, //!< Gain of the image (only for those cameras that support). CAP_PROP_EXPOSURE =15, //!< Exposure (only for those cameras that support). - CAP_PROP_CONVERT_RGB =16, //!< Boolean flags indicating whether images should be converted to BGR.
+ CAP_PROP_CONVERT_RGB =16, //!< Boolean flags indicating whether images should be converted to RGB.
//!< *GStreamer note*: The flag is ignored in case if custom pipeline is used. It's user responsibility to interpret pipeline output. CAP_PROP_WHITE_BALANCE_BLUE_U =17, //!< Currently unsupported. CAP_PROP_RECTIFICATION =18, //!< Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently). @@ -168,7 +168,7 @@ enum VideoCaptureProperties { CAP_PROP_TRIGGER =24, CAP_PROP_TRIGGER_DELAY =25, CAP_PROP_WHITE_BALANCE_RED_V =26, - CAP_PROP_ZOOM =27, //!< Android: May switch physical cameras/lenses. Factor and range are hardware-dependent. + CAP_PROP_ZOOM =27, CAP_PROP_FOCUS =28, CAP_PROP_GUID =29, CAP_PROP_ISO_SPEED =30, @@ -268,7 +268,6 @@ enum VideoAccelerationType VIDEO_ACCELERATION_D3D11 = 2, //!< DirectX 11 VIDEO_ACCELERATION_VAAPI = 3, //!< VAAPI VIDEO_ACCELERATION_MFX = 4, //!< libmfx (Intel MediaSDK/oneVPL) - VIDEO_ACCELERATION_DRM = 5, //!< Raspberry Pi V4 }; //! @} Hardware acceleration support @@ -714,19 +713,6 @@ enum VideoCaptureOBSensorProperties{ CAP_PROP_OBSENSOR_INTRINSIC_FY=26002, CAP_PROP_OBSENSOR_INTRINSIC_CX=26003, CAP_PROP_OBSENSOR_INTRINSIC_CY=26004, - CAP_PROP_OBSENSOR_RGB_POS_MSEC=26005, - CAP_PROP_OBSENSOR_DEPTH_POS_MSEC=26006, - CAP_PROP_OBSENSOR_DEPTH_WIDTH=26007, - CAP_PROP_OBSENSOR_DEPTH_HEIGHT=26008, - CAP_PROP_OBSENSOR_DEPTH_FPS=26009, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K1=26010, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K2=26011, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K3=26012, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K4=26013, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K5=26014, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_K6=26015, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1=26016, - CAP_PROP_OBSENSOR_COLOR_DISTORTION_P2=26017 }; //! @} OBSENSOR @@ -740,14 +726,8 @@ class CV_EXPORTS_W IStreamReader public: virtual ~IStreamReader(); - /** @brief Read bytes from stream - * - * @param buffer already allocated buffer of at least @p size bytes - * @param size maximum number of bytes to read - * - * @return actual number of read bytes - */ - CV_WRAP virtual long long read(char* buffer, long long size) = 0; + /** @brief Read bytes from stream */ + virtual long long read(char* buffer, long long size) = 0; /** @brief Sets the stream position * @@ -756,7 +736,7 @@ public: * * @see fseek */ - CV_WRAP virtual long long seek(long long offset, int origin) = 0; + virtual long long seek(long long offset, int origin) = 0; }; class IVideoCapture; diff --git a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/world.hpp b/vendor/opensource/opencv/gcc/include/opencv4/opencv2/world.hpp deleted file mode 100644 index 4902c2f2a64544b473ed919b83c9363658cad4e6..0000000000000000000000000000000000000000 --- a/vendor/opensource/opencv/gcc/include/opencv4/opencv2/world.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef OPENCV_WORLD_HPP -#define OPENCV_WORLD_HPP - -#include "opencv2/core.hpp" - -#ifdef __cplusplus -namespace cv -{ - -CV_EXPORTS_W bool initAll(); - -} - -#endif - -#endif diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so new file mode 120000 index 0000000000000000000000000000000000000000..aba6a8457b231cd134608eeb59d4cc32361e0c07 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so @@ -0,0 +1 @@ +libopencv_calib3d.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..17e6e2b7b170ba1f4e28f3b1ebc3ddf0a869d2b5 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..84e2f9948f745162315c81ce7cd52d41784c889a --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_calib3d.so.411 @@ -0,0 +1 @@ +libopencv_calib3d.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_core.so b/vendor/opensource/opencv/gcc/lib/libopencv_core.so new file mode 120000 index 0000000000000000000000000000000000000000..79b403008690b735b2f8093664fa337613ac4ff6 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_core.so @@ -0,0 +1 @@ +libopencv_core.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_core.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_core.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..85ce2b9592a94d4f6758aee2fee99f409dbe803d Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_core.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_core.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_core.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..ddc2f75416bd55da44585139f894622ed603e01c --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_core.so.411 @@ -0,0 +1 @@ +libopencv_core.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so new file mode 120000 index 0000000000000000000000000000000000000000..0d14600a1c9e612114efaf345b023f92e5d68522 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so @@ -0,0 +1 @@ +libopencv_dnn.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..aa2c51801606c7d64ba9f2d8a027a39ce9f8de97 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..3a01052ed5f85a82b380363f1637532aa001436c --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_dnn.so.411 @@ -0,0 +1 @@ +libopencv_dnn.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so new file mode 120000 index 0000000000000000000000000000000000000000..c344ab85c8a36b9ea060392ef251f6474af768bd --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so @@ -0,0 +1 @@ +libopencv_features2d.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..86f92c03a4e5f7382d864b316523759adfdae0cb Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..dd06b9198b93951ba6bc2e5095c94a1424ccc7ab --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_features2d.so.411 @@ -0,0 +1 @@ +libopencv_features2d.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_flann.so b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so new file mode 120000 index 0000000000000000000000000000000000000000..f72c2ab42db16e9e6e26c7641546c2aebf97e9cd --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so @@ -0,0 +1 @@ +libopencv_flann.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..f43008b8f16f05df940d3fdaa594f08d5b967fa3 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..cb3a7f8104c837b91b4ac5439b82df528f3f9bba --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_flann.so.411 @@ -0,0 +1 @@ +libopencv_flann.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so new file mode 120000 index 0000000000000000000000000000000000000000..3d3116106cb97f61e40706ca8267b453bb173ae5 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so @@ -0,0 +1 @@ +libopencv_gapi.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..8a35bd674e1b8cb172dcb7b6e633f7e237021798 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..3eda00c8c3a404700832e8f55a8f6d6c846eb317 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_gapi.so.411 @@ -0,0 +1 @@ +libopencv_gapi.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so new file mode 120000 index 0000000000000000000000000000000000000000..79536f7063d45a9c135e808eff8bf389970578d2 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so @@ -0,0 +1 @@ +libopencv_highgui.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..ead76741cd6159c62811db1c214b2e0c4a5c7c43 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..7a62afab3c587db5bf4a02576b5877a875c76ea9 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_highgui.so.411 @@ -0,0 +1 @@ +libopencv_highgui.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so new file mode 120000 index 0000000000000000000000000000000000000000..01a776f9a120a5919c040df977c7a0d55e462e6f --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so @@ -0,0 +1 @@ +libopencv_imgcodecs.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..e9341993ac5c80dcd03eb7dc133b9c054f687dbe Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..83846f50910cf5ee051f2723b070efee9fa2874b --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_imgcodecs.so.411 @@ -0,0 +1 @@ +libopencv_imgcodecs.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so new file mode 120000 index 0000000000000000000000000000000000000000..8b058b7a05391e12ee7e50d8c1c1b001520f3643 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so @@ -0,0 +1 @@ +libopencv_imgproc.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..97e9983c1746a1014d5d993882b3b75d45c01c87 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..d5b7300a9b8f0facbb8313a4bcce4e0e979b4fc4 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_imgproc.so.411 @@ -0,0 +1 @@ +libopencv_imgproc.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_ml.so b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so new file mode 120000 index 0000000000000000000000000000000000000000..828c4b7e6121c38d1a66183517ad4b31123602d0 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so @@ -0,0 +1 @@ +libopencv_ml.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..7858e32512a5d1e48c4e402faf06a1d36b974477 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..5c43b2ecd5accc1de5076156b3f50f40d8fc809b --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_ml.so.411 @@ -0,0 +1 @@ +libopencv_ml.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so new file mode 120000 index 0000000000000000000000000000000000000000..6dedee5a8b279fd30e09e710d755aa10123c56e9 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so @@ -0,0 +1 @@ +libopencv_objdetect.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..28796d7005eb765c72e0c492342fb81782e434e5 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..120d30078d93f2e42ab1a178f9a54fe3b2867eb2 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_objdetect.so.411 @@ -0,0 +1 @@ +libopencv_objdetect.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_photo.so b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so new file mode 120000 index 0000000000000000000000000000000000000000..c58a894d6e8d98748530336ffb22893ceabec9c0 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so @@ -0,0 +1 @@ +libopencv_photo.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..eac4b1184bc8a3f3895a65d56c98ee60691f742b Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..fc93078ee8812f47e2ccf06a27c5413949ac2be9 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_photo.so.411 @@ -0,0 +1 @@ +libopencv_photo.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so new file mode 120000 index 0000000000000000000000000000000000000000..4888fc1369c06cce3e2658e9f0f5d94726eadaf1 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so @@ -0,0 +1 @@ +libopencv_stitching.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..c92bc856d9e600c322d1ac5732adbfaccd0c4cd3 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..762025e2d98b26d3615511ebbdab11e2e3ba5489 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_stitching.so.411 @@ -0,0 +1 @@ +libopencv_stitching.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_video.so b/vendor/opensource/opencv/gcc/lib/libopencv_video.so new file mode 120000 index 0000000000000000000000000000000000000000..28b6465266b7c7174f1665028b4e5de3d8a3e535 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_video.so @@ -0,0 +1 @@ +libopencv_video.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_video.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_video.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..24c148ad1a06f3a936c553e468721f3b58216232 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_video.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_video.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_video.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..01e1770392e6ae671e41da2dd158a6005f534a2e --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_video.so.411 @@ -0,0 +1 @@ +libopencv_video.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so new file mode 120000 index 0000000000000000000000000000000000000000..1322287ccc886833a3fdbbf974377f354527ef48 --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so @@ -0,0 +1 @@ +libopencv_videoio.so.411 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.4.11.0 b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.4.11.0 new file mode 100644 index 0000000000000000000000000000000000000000..65ab2a5c118710760837d3fb88a14bed2c5787d7 Binary files /dev/null and b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.4.11.0 differ diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.411 b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.411 new file mode 120000 index 0000000000000000000000000000000000000000..e5a6a328015d564808e562f8d7a52b0982a5a31f --- /dev/null +++ b/vendor/opensource/opencv/gcc/lib/libopencv_videoio.so.411 @@ -0,0 +1 @@ +libopencv_videoio.so.4.11.0 \ No newline at end of file diff --git a/vendor/opensource/opencv/gcc/lib/libopencv_world.so b/vendor/opensource/opencv/gcc/lib/libopencv_world.so deleted file mode 100755 index 4d918b2c74660db85498a2686c08abe6cfd7efc2..0000000000000000000000000000000000000000 Binary files a/vendor/opensource/opencv/gcc/lib/libopencv_world.so and /dev/null differ diff --git a/vendor/opensource/opensource_softwares.json b/vendor/opensource/opensource_softwares.json index c34105c8033a1e3c12cb8a8568c114b720b459f9..9a8a0632de7c5b9e3d167e7833a78181cbc3960c 100644 --- a/vendor/opensource/opensource_softwares.json +++ b/vendor/opensource/opensource_softwares.json @@ -1,6 +1,7 @@ { "pkg_name_versions" : [ - "opencv=4.13==vendor/opensource/opencv" + "opencv=4.11==vendor/opensource/opencv" "osd=1.0.0==vendor/opensource/osd" + "spdlog=1.15.3==vendor/opensource/log_lib/spdlog" ] } diff --git a/vendor/zsks/README.md b/vendor/zsks/README.md index 3e308534cf22253f6d5ea606e8ccd0b7d113e127..99374531360284bb442dde5b7ba83ff4980d8268 100755 --- a/vendor/zsks/README.md +++ b/vendor/zsks/README.md @@ -17,10 +17,10 @@ | 操作系统 | 下载链接 | | --------------------- | ------------------------------------------------------------ | -| OpenHarmony桌面版本 | 链接: https://pan.baidu.com/s/17f-0xEXUlxoANzzhA6xrCw?pwd=fp6e | -| OpenHarmony无桌面版本 | 链接: https://pan.baidu.com/s/1-_3tiZFdrrs3mAck9S3ezg?pwd=tzd2 | -| Ubuntu22.04桌面版本 | 链接:https://pan.baidu.com/s/1Kp26L-aPFUzFV6wJ9q2L6Q?pwd=udw7 | -| Ubuntu22.04无桌面版本 | 链接: https://pan.baidu.com/s/1LWi3o_COdMupS03IFTnCKw?pwd=b9by | +| OpenHarmony桌面版本 | 链接: https://pan.baidu.com/s/1sWS8B6MFO1_bSn6tiRpZ-Q 提取码: 1jq8 | +| OpenHarmony无桌面版本 | 链接: https://pan.baidu.com/s/1I0SQjVPaYHfwwcmy9w0FhQ 提取码: mn7w | +| Ubuntu24.04桌面版本 | 链接: https://pan.baidu.com/s/1CbOAy5wjvcRiwE4WRMe3cQ 提取码: w584 | +| Ubuntu24.04无桌面版本 | 链接: https://pan.baidu.com/s/1csbikvIlU4uARZ81YrhmiQ 提取码: e9xe | @@ -55,6 +55,12 @@ * 本案例主要使用pytorch框架,基于YoloV8,使用大量的特殊场景下的人脸数据,训练出来的强逆光下的人脸检测模型,通过USB Camera,将采集到的图片送到人脸检测模型中进行推理,当检测到人脸时,会在人脸区域画出矩形,并实时的通过外接HDMI线显示在外接显示屏上。 +### [3.6.opencv_ive](./demo/opencv_ive/README.md) + +* 本案例主要是中山旷视基于opencv开发的IVE算子加速API接口,方便开发者在调用opencv原生算子API的同时实现了IVE硬件加速的效果。 + + + ## 4.第三方软件 | 第三方软件 | 软件介绍 | 开发文档 | diff --git a/vendor/zsks/demo/Makefile b/vendor/zsks/demo/Makefile old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/Makefile.param b/vendor/zsks/demo/Makefile.param old mode 100755 new mode 100644 index e2c827444820227f4fecdd00c590479b747c73ea..0a0ad8d5adfcb23e4558e5ebfd0a74787732e768 --- a/vendor/zsks/demo/Makefile.param +++ b/vendor/zsks/demo/Makefile.param @@ -35,41 +35,40 @@ SENSOR1_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT SENSOR2_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT SENSOR3_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT -MPI_LIBS := $(REL_LIB)/libss_mpi.a +MPI_LIBS := -lss_mpi ifeq ($(CONFIG_OT_ISP_SUPPORT), y) -MPI_LIBS += $(REL_LIB)/libss_ae.a -MPI_LIBS += $(REL_LIB)/libss_isp.a -MPI_LIBS += $(REL_LIB)/libot_isp.a -MPI_LIBS += $(REL_LIB)/libss_awb.a -MPI_LIBS += $(REL_LIB)/libss_dehaze.a -MPI_LIBS += $(REL_LIB)/libss_extend_stats.a -MPI_LIBS += $(REL_LIB)/libss_drc.a -MPI_LIBS += $(REL_LIB)/libss_ldci.a -MPI_LIBS += $(REL_LIB)/libss_crb.a -MPI_LIBS += $(REL_LIB)/libss_bnr.a -MPI_LIBS += $(REL_LIB)/libss_calcflicker.a -MPI_LIBS += $(REL_LIB)/libss_ir_auto.a -MPI_LIBS += $(REL_LIB)/libss_acs.a -MPI_LIBS += $(REL_LIB)/libss_acs.a -MPI_LIBS += $(REL_LIB)/libsns_hy_s0603.a -MPI_LIBS += $(REL_LIB)/libsns_os08a20.a -MPI_LIBS += $(REL_LIB)/libsns_imx347_slave.a -MPI_LIBS += $(REL_LIB)/libsns_os04a10.a -MPI_LIBS += $(REL_LIB)/libsns_sc450ai.a -MPI_LIBS += $(REL_LIB)/libsns_sc450ai_2l.a +MPI_LIBS += -lss_ae +MPI_LIBS += -lss_isp +MPI_LIBS += -lot_isp +MPI_LIBS += -lss_awb +MPI_LIBS += -lss_dehaze +MPI_LIBS += -lss_extend_stats +MPI_LIBS += -lss_drc +MPI_LIBS += -lss_ldci +MPI_LIBS += -lss_crb +MPI_LIBS += -lss_bnr +MPI_LIBS += -lss_calcflicker +MPI_LIBS += -lss_ir_auto +MPI_LIBS += -lss_acs +MPI_LIBS += -lsns_hy_s0603 +MPI_LIBS += -lsns_os08a20 +MPI_LIBS += -lsns_imx347_slave +MPI_LIBS += -lsns_os04a10 +MPI_LIBS += -lsns_sc450ai +MPI_LIBS += -lsns_sc450ai_2l endif ifeq ($(CONFIG_OT_AUDIO_SUPPORT), y) -AUDIO_LIBA := $(REL_LIB)/libss_voice_engine.a -AUDIO_LIBA += $(REL_LIB)/libss_upvqe.a -AUDIO_LIBA += $(REL_LIB)/libss_dnvqe.a -AUDIO_LIBA += $(REL_LIB)/libaac_comm.a -AUDIO_LIBA += $(REL_LIB)/libaac_enc.a -AUDIO_LIBA += $(REL_LIB)/libaac_dec.a -AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.a -AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.a +AUDIO_LIBA := -lss_voice_engine +AUDIO_LIBA += -lss_upvqe +AUDIO_LIBA += -lss_dnvqe +AUDIO_LIBA += -laac_comm +AUDIO_LIBA += -laac_enc +AUDIO_LIBA += -laac_dec +AUDIO_LIBA += -laac_sbr_enc +AUDIO_LIBA += -laac_sbr_dec endif COMMON_DIR ?= $(SDK_PATH)/mpp/sample/common @@ -128,22 +127,22 @@ AUDIO_MODULE_LIB_TYPE ?= AUDIO_LIB_TYPE_STATIC ifeq ($(AUDIO_MODULE_LIB_TYPE), AUDIO_LIB_TYPE_STATIC) ##### VQE ##### CFLAGS += -DOT_VQE_USE_STATIC_MODULE_REGISTER - AUDIO_LIBA += $(REL_LIB)/libvqe_res.a - AUDIO_LIBA += $(REL_LIB)/libvqe_record.a - AUDIO_LIBA += $(REL_LIB)/libvqe_hpf.a - AUDIO_LIBA += $(REL_LIB)/libvqe_anr.a - AUDIO_LIBA += $(REL_LIB)/libvqe_aec.a - AUDIO_LIBA += $(REL_LIB)/libvqe_agc.a - AUDIO_LIBA += $(REL_LIB)/libvqe_eq.a - AUDIO_LIBA += $(REL_LIB)/libvqe_talkv2.a + AUDIO_LIBA += -lvqe_res + AUDIO_LIBA += -lvqe_record + AUDIO_LIBA += -lvqe_hpf + AUDIO_LIBA += -lvqe_anr + AUDIO_LIBA += -lvqe_aec + AUDIO_LIBA += -lvqe_agc + AUDIO_LIBA += -lvqe_eq + AUDIO_LIBA += -lvqe_talkv2 ##### AAC ##### CFLAGS += -DOT_AAC_USE_STATIC_MODULE_REGISTER - AUDIO_LIBA += $(REL_LIB)/libaac_dec.a - AUDIO_LIBA += $(REL_LIB)/libaac_enc.a - AUDIO_LIBA += $(REL_LIB)/libaac_comm.a + AUDIO_LIBA += -laac_dec + AUDIO_LIBA += -laac_enc + AUDIO_LIBA += -laac_comm CFLAGS += -DOT_AAC_HAVE_SBR_LIB - AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.a - AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.a + AUDIO_LIBA += -laac_sbr_dec + AUDIO_LIBA += -laac_sbr_enc endif endif @@ -152,7 +151,7 @@ GYRO_DIS ?= n ifeq ($(GYRO_DIS), y) CFLAGS += -DOT_GYRODIS_SUPPORT - MPI_LIBS += $(REL_LIB)/libss_motionfusion.a + MPI_LIBS += -lss_motionfusion endif ######################################################################### @@ -192,9 +191,9 @@ MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/ipcmsg/include MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/datafifo/include ifeq ($(CONFIG_DRIVER_SPACE_TYPE),user_space) -MPI_LIBS += $(REL_LIB)/svp_npu/libsvp_acl.a -MPI_LIBS += -L$(REL_LIB)/svp_npu -lprotobuf-c -SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/extdrv +MPI_LIBS += -lsvp_acl +MPI_LIBS += -lprotobuf-c +SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/svp_npu -L$(REL_LIB)/extdrv SDK_LIB := $(SDK_LIB_PATH) SDK_LIB += -l$(KO_PREFIX)_osal SDK_LIB += -l$(KO_PREFIX)_base @@ -217,16 +216,16 @@ SDK_LIB += -l$(KO_PREFIX)_vi SDK_LIB += -l$(KO_PREFIX)_mpi_isp SDK_LIB += -l$(KO_PREFIX)_rc SDK_LIB += -l$(KO_PREFIX)_jpegd -SDK_LIB += $(REL_LIB)/libss_hdmi.a +SDK_LIB += -lss_hdmi SDK_LIB += -l$(KO_PREFIX)_vfmw SDK_LIB += -l$(KO_PREFIX)_gdc SDK_LIB += -l$(KO_PREFIX)_dis SDK_LIB += -l$(KO_PREFIX)_irq -SDK_LIB += $(REL_LIB)/libss_dpu_match.a -SDK_LIB += $(REL_LIB)/libss_dpu_rect.a -SDK_LIB += $(REL_LIB)/libss_mau.a -SDK_LIB += $(REL_LIB)/libss_ive.a -SDK_LIB += $(REL_LIB)/libss_pqp.a +SDK_LIB += -lss_dpu_match +SDK_LIB += -lss_dpu_rect +SDK_LIB += -lss_mau +SDK_LIB += -lss_ive +SDK_LIB += -lss_pqp #SDK_LIB += -l$(KO_PREFIX)_avs # SDK_LIB += -l$(KO_PREFIX)_mcf # SDK_LIB += -l$(KO_PREFIX)_mcf_vi @@ -247,6 +246,14 @@ SDK_LIB += -l$(KO_PREFIX)_acodec MPI_LIBS += $(AUDIO_LIBA) endif +ifeq ($(GYRO_DIS),y) +SDK_LIB += -l$(KO_PREFIX)_motionfusion_user +SDK_LIB += -l$(KO_PREFIX)_gyrodis +SDK_LIB += -l$(KO_PREFIX)_spi +SDK_LIB += -lmotionsensor_mng +SDK_LIB += -lmotionsensor_chip +endif + ifeq ($(CONFIG_OT_HEIF_SUPPORT),y) SDK_LIB += -lheif SDK_LIB += -lfileformat diff --git a/vendor/zsks/demo/face_detection/Makefile b/vendor/zsks/demo/face_detection/Makefile old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/README.md b/vendor/zsks/demo/face_detection/README.md old mode 100755 new mode 100644 index 8df20fab531fb6b95782f45d7ded04d843f34739..f04e2a9867193d57cf96551e2b0da9b95918d26a --- a/vendor/zsks/demo/face_detection/README.md +++ b/vendor/zsks/demo/face_detection/README.md @@ -1,130 +1,121 @@ -# 2.5、face_detection 操作指导 - -# 2.5.1、face_detection 程序简介 - -- face_detection sample基于SS928V100平台开发,以zsks套件为例,face_detection sample是通过USB Camera,将采集到的图片送到人脸检测模型中进行推理,当检测到人脸时,会在人脸区域画出矩形框,并通过外接HDMI线实时的显示在外接显示屏上。 -- face_detection 案例主要是使用pytorch框架,基于YoloV8网络,使用widerface、FDDB、UFDD等开源数据集,共1.3万多张训练出来在强光、逆光、暗光下的人脸检测模型。 - -# 2.5.2、目录 - -```shell -pegasus/vendor/zsks/demo/face_detection -|── data # 模型文件 -|── Makefile # 编译脚本 -└── face_detection.c # face_detection sample业务代码 -``` - -![image-20250919144926220](pic/image-20250919144926220-20260428140932-idp5adr.png) - -- 根据外接显示屏的输出参数进行配置,比如说我的外接显示屏的输出是1080P60,如果smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c ample_common_svp_get_def_vo_cfg函数的intf_sync为OT_VO_OUT_1080P30,则需要把他修改为OT_VO_OUT_1080P60。 - -![image-20251023102053075](pic/image-20251023102053075-20260428140932-n1f67mi.png) - -# 2.5.3、编译 - -- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 -- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -- 步骤2:使用Makefile的方式进行单编 -- 在Ubuntu的命令行终端,分步执行下面的命令,单编 face_detection sample -- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 - - ``` - cd pegasus/vendor/zsks/demo/face_detection - - # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - # 检查SYSROOT_PATH配置是否生效。 - echo $SYSROOT_PATH - - make LLVM=1 clean && make LLVM=1 - ``` - - - 在face_detection/out目录下,生成一个名为 main 的 可执行文件,如下图所示: - - ![image-20251231153903404](pic/image-20251231153903404-20260428140932-bwwdji0.png) - - ![image-20251231153931716](pic/image-20251231153931716-20260428140932-fh3rjpr.png) - -# 2.5.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 - -**方式一:使用SD卡进行资料文件的拷贝** - -- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 - -![image-20221114150205685](pic/image-20221114150205685-20260428140932-5wr44ho.png) - -- 步骤1:将编译后生成的可执行文件main和资源文件data,拷贝到SD卡中。 - -![image-20251023100347550](pic/image-20251023100347550-20260428140932-8uq0w6x.png) - -- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 - -![image](pic/image-20260428150712-7avg3km.png) - -- 在开发板的终端,执行下面的命令进行SD卡的挂载 - - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) - -```shell -mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 -``` - -- 挂载成功后,如下图所示: - -![image-20251023102549783](pic/image-20251023102549783-20260428140932-ot0sp5o.png) - -**方式二:使用NFS挂载的方式进行资料文件的拷贝** - -- 首先需要自己准备一根网线 -- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -- 步骤2:将编译后生成的可执行文件main和资源文件data,拷贝到Windows的nfs共享路径下 - -![image-20251023100136196](pic/image-20251023100136196-20260428140932-ulpz1fm.png) - -- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 - - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 - -``` -ifconfig eth0 192.168.100.100 - -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251023101210815](pic/image-20251023101210815-20260428140932-ivaoivl.png) - -# 2.5.5、硬件连接 - -- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 - -![image](pic/image-20260428151316-vwbp8qg.png) - -- 将USB 摄像头接在EulerPi开发板的USB接口上。 - -![image](pic/image-20260428151432-6nzax2h.png) - -# 2.5.6、功能验证 - -- 在开发板的终端执行下面的命令,运行可执行文件 - -``` -cd /mnt/demo_ohos/face_detection - -chmod +x ./out/main - -./out/main -``` - -![image-20251023101503216](pic/image-20251023101503216-20260428140932-7x42j3q.png) - -- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -![image](pic/image-20260428151528-smzz9s8.png) - -- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 - -![image-20250919151018659](pic/image-20250919151018659-20260428140932-vqlpx5k.png) - -- 正常情况下,我们会在外接显示屏上看到人脸的区域被框出来,且在比较黑暗或者强逆光条件下,也能比较好的检测到人脸。![image-20250919151605632](pic/image-20250919151605632-20260428140932-zmbenmx.png) -- 敲两下回车即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310-20260428140932-hm8sbdn.png) +# 3.5、face_detection 操作指导 + +# 3.5.1、face_detection 程序简介 + +- face_detection sample基于SS928V100平台开发,以zsks套件为例,face_detection sample是通过USB Camera,将采集到的图片送到人脸检测模型中进行推理,当检测到人脸时,会在人脸区域画出矩形框,并通过外接HDMI线实时的显示在外接显示屏上。 +- face_detection 案例主要是使用pytorch框架,基于YoloV8网络,使用widerface、FDDB、UFDD等开源数据集,共1.3万多张训练出来在强光、逆光、暗光下的人脸检测模型。 + +# 3.5.2、目录 + +```shell +pegasus/vendor/zsks/demo/face_detection +|── data # 模型文件 +|── Makefile # 编译脚本 +└── face_detection.c # face_detection sample业务代码 +``` + +- 根据外接显示屏的输出参数进行配置,比如说我的外接显示屏的输出是1080P60,如果smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c ample_common_svp_get_def_vo_cfg函数的intf_sync为OT_VO_OUT_1080P30,则需要把他修改为OT_VO_OUT_1080P60。 + +![image-20251023102053075](pic/image-20251023102053075-20260428140932-n1f67mi.png) + +# 3.5.3、编译 + +- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 +- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 +- 步骤2:使用Makefile的方式进行单编 +- 在Ubuntu的命令行终端,分步执行下面的命令,单编 face_detection sample +- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + + ``` + cd pegasus/vendor/zsks/demo/face_detection + + # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 + export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + # 检查SYSROOT_PATH配置是否生效。 + echo $SYSROOT_PATH + + make LLVM=1 clean && make LLVM=1 + ``` + + - 在face_detection/out目录下,生成一个名为 main 的 可执行文件![image-20251231153931716](pic/image-20251231153931716-20260428140932-fh3rjpr.png) + + +# 3.5.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +- 步骤1:将编译后生成的可执行文件main和资源文件data,拷贝到SD卡中。 + +![image-20251023100347550](pic/image-20251023100347550-20260428140932-8uq0w6x.png) + +- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +![image](pic/image-20260428150712-7avg3km.png) + +- 在开发板的终端,执行下面的命令进行SD卡的挂载 + - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +- 挂载成功后,如下图所示: + +![image-20251023102549783](pic/image-20251023102549783-20260428140932-ot0sp5o.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +- 首先需要自己准备一根网线 +- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +- 步骤2:将编译后生成的可执行文件main和资源文件data,拷贝到Windows的nfs共享路径下 + +![image-20251023100136196](pic/image-20251023100136196-20260428140932-ulpz1fm.png) + +- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + +``` +ifconfig eth0 192.168.100.100 + +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251023101210815](pic/image-20251023101210815-20260428140932-ivaoivl.png) + +# 3.5.5、硬件连接 + +- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image](pic/image-20260428151316-vwbp8qg.png) + +- 将USB 摄像头接在EulerPi开发板的USB接口上。 + +![image](pic/image-20260428151432-6nzax2h.png) + +# 3.5.6、功能验证 + +- 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt/demo_ohos/face_detection + +chmod +x ./out/main + +./out/main +``` + +- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +![image](pic/image-20260428151528-smzz9s8.png) + +- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659-20260428140932-vqlpx5k.png) + +- 正常情况下,我们会在外接显示屏上看到人脸的区域被框出来,且在比较黑暗或者强逆光条件下,也能比较好的检测到人脸。![image-20250919151605632](pic/image-20250919151605632-20260428140932-zmbenmx.png) +- 敲两下回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310-20260428140932-hm8sbdn.png) diff --git a/vendor/zsks/demo/face_detection/data/model/face_detection.om b/vendor/zsks/demo/face_detection/data/model/face_detection.om old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/face_detection.c b/vendor/zsks/demo/face_detection/face_detection.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20221114150205685-20260428140932-5wr44ho.png b/vendor/zsks/demo/face_detection/pic/image-20221114150205685-20260428140932-5wr44ho.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20250919144926220-20260428140932-idp5adr.png b/vendor/zsks/demo/face_detection/pic/image-20250919144926220-20260428140932-idp5adr.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20250919151018659-20260428140932-vqlpx5k.png b/vendor/zsks/demo/face_detection/pic/image-20250919151018659-20260428140932-vqlpx5k.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20250919151519310-20260428140932-hm8sbdn.png b/vendor/zsks/demo/face_detection/pic/image-20250919151519310-20260428140932-hm8sbdn.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20250919151605632-20260428140932-zmbenmx.png b/vendor/zsks/demo/face_detection/pic/image-20250919151605632-20260428140932-zmbenmx.png old mode 100755 new mode 100644 index c6aa9aad5685495d6bad5ba5d4e0c09e31ed3c7a..e4aa1e3dc2d8bedf8a9cb2235d4104b61fff509b Binary files a/vendor/zsks/demo/face_detection/pic/image-20250919151605632-20260428140932-zmbenmx.png and b/vendor/zsks/demo/face_detection/pic/image-20250919151605632-20260428140932-zmbenmx.png differ diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023100136196-20260428140932-ulpz1fm.png b/vendor/zsks/demo/face_detection/pic/image-20251023100136196-20260428140932-ulpz1fm.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023100347550-20260428140932-8uq0w6x.png b/vendor/zsks/demo/face_detection/pic/image-20251023100347550-20260428140932-8uq0w6x.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023101210815-20260428140932-ivaoivl.png b/vendor/zsks/demo/face_detection/pic/image-20251023101210815-20260428140932-ivaoivl.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023101503216-20260428140932-7x42j3q.png b/vendor/zsks/demo/face_detection/pic/image-20251023101503216-20260428140932-7x42j3q.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023102053075-20260428140932-n1f67mi.png b/vendor/zsks/demo/face_detection/pic/image-20251023102053075-20260428140932-n1f67mi.png old mode 100755 new mode 100644 index 6fc62dd35e3dcfeb36a6e3ba1e7cea3e008660ed..bd5f4022245d5ecf9f08ae429a099d1bb436c31b Binary files a/vendor/zsks/demo/face_detection/pic/image-20251023102053075-20260428140932-n1f67mi.png and b/vendor/zsks/demo/face_detection/pic/image-20251023102053075-20260428140932-n1f67mi.png differ diff --git a/vendor/zsks/demo/face_detection/pic/image-20251023102549783-20260428140932-ot0sp5o.png b/vendor/zsks/demo/face_detection/pic/image-20251023102549783-20260428140932-ot0sp5o.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251231153903404-20260428140932-bwwdji0.png b/vendor/zsks/demo/face_detection/pic/image-20251231153903404-20260428140932-bwwdji0.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20251231153931716-20260428140932-fh3rjpr.png b/vendor/zsks/demo/face_detection/pic/image-20251231153931716-20260428140932-fh3rjpr.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/face_detection/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/face_detection/pic/image-20260428150712-7avg3km.png old mode 100755 new mode 100644 index df435036941a44a6cb7417ceb227de759f7b23b7..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files a/vendor/zsks/demo/face_detection/pic/image-20260428150712-7avg3km.png and b/vendor/zsks/demo/face_detection/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/face_detection/pic/image-20260428151316-vwbp8qg.png b/vendor/zsks/demo/face_detection/pic/image-20260428151316-vwbp8qg.png old mode 100755 new mode 100644 index 15f31ab2465ae782b7f989394636f63afb3adf56..d9685f02d7410d1873f90b5b2cc0280f159f26aa Binary files a/vendor/zsks/demo/face_detection/pic/image-20260428151316-vwbp8qg.png and b/vendor/zsks/demo/face_detection/pic/image-20260428151316-vwbp8qg.png differ diff --git a/vendor/zsks/demo/face_detection/pic/image-20260428151432-6nzax2h.png b/vendor/zsks/demo/face_detection/pic/image-20260428151432-6nzax2h.png old mode 100755 new mode 100644 index d5caadbf1182a680d8500a5231e60f7e545caf88..a3fac08b2fef75aaa6d7d1e9bf5fb045e029ce82 Binary files a/vendor/zsks/demo/face_detection/pic/image-20260428151432-6nzax2h.png and b/vendor/zsks/demo/face_detection/pic/image-20260428151432-6nzax2h.png differ diff --git a/vendor/zsks/demo/face_detection/pic/image-20260428151528-smzz9s8.png b/vendor/zsks/demo/face_detection/pic/image-20260428151528-smzz9s8.png old mode 100755 new mode 100644 index 77a7bef4a3847c61c98449b68dad4c61fb494d0c..5aeccc9c51038fd22fcc550a3e6c8a5039edb32e Binary files a/vendor/zsks/demo/face_detection/pic/image-20260428151528-smzz9s8.png and b/vendor/zsks/demo/face_detection/pic/image-20260428151528-smzz9s8.png differ diff --git a/vendor/zsks/demo/fruit_identify/Makefile b/vendor/zsks/demo/fruit_identify/Makefile old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/README.md b/vendor/zsks/demo/fruit_identify/README.md old mode 100755 new mode 100644 index db83cfb87e0759b891c8a441c00608bfd75c251f..638dcb246b8ee60b9c508a82d3ef7f1e7684ec4f --- a/vendor/zsks/demo/fruit_identify/README.md +++ b/vendor/zsks/demo/fruit_identify/README.md @@ -1,133 +1,126 @@ -# 2.3、fruit_identify操作指导 - -# 2.3.1、fruit_identify程序简介 - -- fruit_identify sample基于SS928V100平台开发,以zsks套件为例,fruit_identify sample是通过USB Camera,将采集到的图片送到水果检测模型中进行推理,当检测到特定水果时,会通过外接显示屏实时显示水果的种类以及执行度,并框住水果的具体位置,并通过耳机播放出此时识别到的水果类别。 -- fruit_identify案例主要是使用pytorch框架,基于YoloV8网络,使用自行标注的水果数据集训练出来的水果分类模型。 - -## 2.3.2、目录 - -```shell -pegasus/vendor/zsks/demo/fruit_identify -|── common # 基于海思mpp/sample中的svp/common/目录下修改的代码,新增了OSD部分的内容 -|── data # 模型文件和汉字库 -|── fruit_audio # 不同水果的音频文件 -|── Makefile # 编译脚本 -|── fruit_identify.c # fruit_identif sample业务代码 -|── sample_audio.c # 音频播放的业务代码 -└── sample_audio.h # 音频播放的头文件 -``` - -![image-20250919173612332](pic/image-20250919173612332-20260428152157-lq8l0qb.png) - -## 2.3.3、编译 - -- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 -- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -- 步骤2:使用Makefile的方式进行单编 -- 在Ubuntu的命令行终端,分步执行下面的命令,单编 fruit_identify sample -- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 - - ``` - cd pegasus/vendor/zsks/demo/fruit_identify - - # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - # 检查SYSROOT_PATH配置是否生效。 - echo $SYSROOT_PATH - - make LLVM=1 clean && make LLVM=1 - ``` - - - 在fruit_identify/out目录下,生成一个名为main的 可执行文件,如下图所示: - - ![image-20251231154526977](pic/image-20251231154526977-20260428152157-80vilnr.png) - -![image-20251231154554388](pic/image-20251231154554388-20260428152157-dx4c3in.png) - -## 2.3.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 - -**方式一:使用SD卡进行资料文件的拷贝** - -- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 - -![image-20221114150205685](pic/image-20221114150205685-20260428152157-2wa664w.png) - -- 步骤1:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到SD卡中。 - -![image-20251023103623167](pic/image-20251023103623167-20260428152157-g1j5fuo.png) - -- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 - -![image](pic/image-20260428150712-7avg3km.png) - -- 在开发板的终端,执行下面的命令进行SD卡的挂载 - - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) - -```shell -mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 -``` - -- 挂载成功后,如下图所示: - -![image-20251023103850695](pic/image-20251023103850695-20260428152157-enj2r9v.png) - -**方式二:使用NFS挂载的方式进行资料文件的拷贝** - -- 首先需要自己准备一根网线 -- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -- 步骤2:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到Windows的nfs共享路径下 - -![image-20251023103700404](pic/image-20251023103700404-20260428152157-ctqedpv.png) - -- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 - - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 - -``` -ifconfig eth0 192.168.100.100 - -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251023103944837](pic/image-20251023103944837-20260428152157-t3ez4aw.png) - -## 2.3.5、硬件连接 - -- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 - -![image](pic/image-20260428151316-vwbp8qg.png) - -- 将USB 摄像头接在zsks开发板的USB接口上并接入小音响。 - -![image](pic/image-20260428154826-pxmtckc.png) - -## 2.3.6、功能验证 - -- 在开发板的终端执行下面的命令,运行可执行文件 - -``` -cd /mnt/nfs/demo_ohos/fruit_identify - -chmod +x ./out/main - -./out/main -``` - -![image-20251023110809454](pic/image-20251023110809454-20260428152158-somvx9v.png) - -- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -![image](pic/image-20260428151528-smzz9s8.png) - -- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 - -![image-20250919151018659](pic/image-20250919151018659-20260428152158-0fgo666.png) - -- 正常情况下,我们会在外接显示屏上看到有水果的区域被框出来。且在框框的左上角显示水果的种类和置信度,并且你可以在开发板上面接上音响,可以听到检测到的水果的具体语音播报。 - -![image-20250919180706355](pic/image-20250919180706355-20260428152158-e023cz8.png) - -- 敲两下回车即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310-20260428152158-fzyt1c4.png) +# 3.3、fruit_identify操作指导 + +# 3.3.1、fruit_identify程序简介 + +- fruit_identify sample基于SS928V100平台开发,以zsks套件为例,fruit_identify sample是通过USB Camera,将采集到的图片送到水果检测模型中进行推理,当检测到特定水果时,会通过外接显示屏实时显示水果的种类以及执行度,并框住水果的具体位置,并通过耳机播放出此时识别到的水果类别。 +- fruit_identify案例主要是使用pytorch框架,基于YoloV8网络,使用自行标注的水果数据集训练出来的水果分类模型。 + +## 3.3.2、目录 + +```shell +pegasus/vendor/zsks/demo/fruit_identify +|── common # 基于海思mpp/sample中的svp/common/目录下修改的代码,新增了OSD部分的内容 +|── data # 模型文件和汉字库 +|── fruit_audio # 不同水果的音频文件 +|── Makefile # 编译脚本 +|── fruit_identify.c # fruit_identif sample业务代码 +|── sample_audio.c # 音频播放的业务代码 +└── sample_audio.h # 音频播放的头文件 +``` + +## 3.3.3、编译 + +- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 +- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 +- 步骤2:使用Makefile的方式进行单编 +- 在Ubuntu的命令行终端,分步执行下面的命令,单编 fruit_identify sample +- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + + ``` + cd pegasus/vendor/zsks/demo/fruit_identify + + # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 + export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + # 检查SYSROOT_PATH配置是否生效。 + echo $SYSROOT_PATH + + make LLVM=1 clean && make LLVM=1 + ``` + + - 在fruit_identify/out目录下,生成一个名为main的 可执行文件,如下图所示: + + +![image-20251231154554388](pic/image-20251231154554388-20260428152157-dx4c3in.png) + +## 3.3.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +- 步骤1:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到SD卡中。 + +![image-20251023103623167](pic/image-20251023103623167-20260428152157-g1j5fuo.png) + +- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +![image](pic/image-20260428150712-7avg3km.png) + +- 在开发板的终端,执行下面的命令进行SD卡的挂载 + - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +- 挂载成功后,如下图所示: + +![image-20251023103850695](pic/image-20251023103850695-20260428152157-enj2r9v.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +- 首先需要自己准备一根网线 +- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +- 步骤2:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到Windows的nfs共享路径下 + +![image-20251023103700404](pic/image-20251023103700404-20260428152157-ctqedpv.png) + +- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + +``` +ifconfig eth0 192.168.100.100 + +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251023103944837](pic/image-20251023103944837-20260428152157-t3ez4aw.png) + +## 3.3.5、硬件连接 + +- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image](pic/image-20260428151316-vwbp8qg.png) + +- 将USB 摄像头接在zsks开发板的USB接口上并接入小音响。 + +![image](pic/image-20260428154826-pxmtckc.png) + +## 3.3.6、功能验证 + +- 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt/nfs/demo_ohos/fruit_identify + +chmod +x ./out/main + +./out/main +``` + +- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +![image](pic/image-20260428151528-smzz9s8.png) + +- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659-20260428152158-0fgo666.png) + +- 正常情况下,我们会在外接显示屏上看到有水果的区域被框出来。且在框框的左上角显示水果的种类和置信度,并且你可以在开发板上面接上音响,可以听到检测到的水果的具体语音播报。 + +![image-20250919180706355](pic/image-20250919180706355-20260428152158-e023cz8.png) + +- 敲两下回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310-20260428152158-fzyt1c4.png) diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp.c b/vendor/zsks/demo/fruit_identify/common/sample_common_svp.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp.h b/vendor/zsks/demo/fruit_identify/common/sample_common_svp.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu.c b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu.h b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu_model.c b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu_model.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu_model.h b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_npu_model.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_osd.c b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_osd.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/common/sample_common_svp_osd.h b/vendor/zsks/demo/fruit_identify/common/sample_common_svp_osd.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/data/hzk/hzk16 b/vendor/zsks/demo/fruit_identify/data/hzk/hzk16 old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/data/model/fruit_identify.om b/vendor/zsks/demo/fruit_identify/data/model/fruit_identify.om old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_audio/apple/audio_chn0.aac b/vendor/zsks/demo/fruit_identify/fruit_audio/apple/audio_chn0.aac old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_audio/banana/audio_chn0.aac b/vendor/zsks/demo/fruit_identify/fruit_audio/banana/audio_chn0.aac old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_audio/orange/audio_chn0.aac b/vendor/zsks/demo/fruit_identify/fruit_audio/orange/audio_chn0.aac old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_audio/pear/audio_chn0.aac b/vendor/zsks/demo/fruit_identify/fruit_audio/pear/audio_chn0.aac old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_audio/watermelon/audio_chn0.aac b/vendor/zsks/demo/fruit_identify/fruit_audio/watermelon/audio_chn0.aac old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/fruit_identify.c b/vendor/zsks/demo/fruit_identify/fruit_identify.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/desktop.ini b/vendor/zsks/demo/fruit_identify/pic/desktop.ini old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20221114150205685-20260428152157-2wa664w.png b/vendor/zsks/demo/fruit_identify/pic/image-20221114150205685-20260428152157-2wa664w.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20250919151018659-20260428152158-0fgo666.png b/vendor/zsks/demo/fruit_identify/pic/image-20250919151018659-20260428152158-0fgo666.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20250919151519310-20260428152158-fzyt1c4.png b/vendor/zsks/demo/fruit_identify/pic/image-20250919151519310-20260428152158-fzyt1c4.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20250919173612332-20260428152157-lq8l0qb.png b/vendor/zsks/demo/fruit_identify/pic/image-20250919173612332-20260428152157-lq8l0qb.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20250919180706355-20260428152158-e023cz8.png b/vendor/zsks/demo/fruit_identify/pic/image-20250919180706355-20260428152158-e023cz8.png old mode 100755 new mode 100644 index ba4971e35c5cdaaf64386cebfa6a896383e61c7d..f5ddd443b56deb137b20cc6624da5f4d57ed18d1 Binary files a/vendor/zsks/demo/fruit_identify/pic/image-20250919180706355-20260428152158-e023cz8.png and b/vendor/zsks/demo/fruit_identify/pic/image-20250919180706355-20260428152158-e023cz8.png differ diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251023103623167-20260428152157-g1j5fuo.png b/vendor/zsks/demo/fruit_identify/pic/image-20251023103623167-20260428152157-g1j5fuo.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251023103700404-20260428152157-ctqedpv.png b/vendor/zsks/demo/fruit_identify/pic/image-20251023103700404-20260428152157-ctqedpv.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251023103850695-20260428152157-enj2r9v.png b/vendor/zsks/demo/fruit_identify/pic/image-20251023103850695-20260428152157-enj2r9v.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251023103944837-20260428152157-t3ez4aw.png b/vendor/zsks/demo/fruit_identify/pic/image-20251023103944837-20260428152157-t3ez4aw.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251023110809454-20260428152158-somvx9v.png b/vendor/zsks/demo/fruit_identify/pic/image-20251023110809454-20260428152158-somvx9v.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251231154526977-20260428152157-80vilnr.png b/vendor/zsks/demo/fruit_identify/pic/image-20251231154526977-20260428152157-80vilnr.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20251231154554388-20260428152157-dx4c3in.png b/vendor/zsks/demo/fruit_identify/pic/image-20251231154554388-20260428152157-dx4c3in.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/fruit_identify/pic/image-20260428150712-7avg3km.png old mode 100755 new mode 100644 index df435036941a44a6cb7417ceb227de759f7b23b7..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files a/vendor/zsks/demo/fruit_identify/pic/image-20260428150712-7avg3km.png and b/vendor/zsks/demo/fruit_identify/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20260428151316-vwbp8qg.png b/vendor/zsks/demo/fruit_identify/pic/image-20260428151316-vwbp8qg.png old mode 100755 new mode 100644 index 15f31ab2465ae782b7f989394636f63afb3adf56..d9685f02d7410d1873f90b5b2cc0280f159f26aa Binary files a/vendor/zsks/demo/fruit_identify/pic/image-20260428151316-vwbp8qg.png and b/vendor/zsks/demo/fruit_identify/pic/image-20260428151316-vwbp8qg.png differ diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20260428151528-smzz9s8.png b/vendor/zsks/demo/fruit_identify/pic/image-20260428151528-smzz9s8.png old mode 100755 new mode 100644 index 77a7bef4a3847c61c98449b68dad4c61fb494d0c..5aeccc9c51038fd22fcc550a3e6c8a5039edb32e Binary files a/vendor/zsks/demo/fruit_identify/pic/image-20260428151528-smzz9s8.png and b/vendor/zsks/demo/fruit_identify/pic/image-20260428151528-smzz9s8.png differ diff --git a/vendor/zsks/demo/fruit_identify/pic/image-20260428154826-pxmtckc.png b/vendor/zsks/demo/fruit_identify/pic/image-20260428154826-pxmtckc.png old mode 100755 new mode 100644 index aadcd8a4788cc1206a833c60d75418c9a72997cb..cd2a105957010eb86cbb057e630d8e7796a320db Binary files a/vendor/zsks/demo/fruit_identify/pic/image-20260428154826-pxmtckc.png and b/vendor/zsks/demo/fruit_identify/pic/image-20260428154826-pxmtckc.png differ diff --git a/vendor/zsks/demo/fruit_identify/sample_audio.c b/vendor/zsks/demo/fruit_identify/sample_audio.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/fruit_identify/sample_audio.h b/vendor/zsks/demo/fruit_identify/sample_audio.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/Makefile b/vendor/zsks/demo/hnr_auto/Makefile old mode 100755 new mode 100644 index 647b010d9c217f31ae18c9c9838c9b85f835d207..91e96475756e9de419eab1ea56724b8f3568dd01 --- a/vendor/zsks/demo/hnr_auto/Makefile +++ b/vendor/zsks/demo/hnr_auto/Makefile @@ -15,8 +15,8 @@ SMP_SRCS += $(wildcard $(PWD)/*.c) # 编译此工程需要包含的库和宏 ifeq ($(CONFIG_OT_ISP_HNR_SUPPORT), y) CFLAGS += -DSAMPLE_HNR_SUPPORT -MPI_LIBS += $(REL_LIB)/libss_pqp.a -MPI_LIBS += $(REL_LIB)/libss_hnr.a +MPI_LIBS += -lss_pqp +MPI_LIBS += -lss_hnr endif # 编译工程所需的mk文件 diff --git a/vendor/zsks/demo/hnr_auto/README.md b/vendor/zsks/demo/hnr_auto/README.md old mode 100755 new mode 100644 index fa27f692daa1c44197f9d447edec8c3820ef9abd..fbd03f9c381ac9b97f9701c58a5a95a0ef4a2fc1 --- a/vendor/zsks/demo/hnr_auto/README.md +++ b/vendor/zsks/demo/hnr_auto/README.md @@ -1,136 +1,128 @@ -# 2.2、hnr_auto操作指导 - -### 2.2.1、hnr_auto程序简介 - -- hnr_auto 基于SS928V100平台开发,以zsks套件为例,hnr_auto 是基于海思的hnr案例,实现夜间超微光的功能,当外接ISO到达一定阈值是,自动切换到hnr模型,使得在黑暗条件下也能清楚看到画面。 - -### 2.2.2、目录 - -```shell -pegasus/vendor/zsks/demo/hnr_auto -|── Makefile # 编译脚本 -|── readme.txt # hnr的操作说明 -└──hnr_auto.c # hnr_auto业务代码 -``` - -![image-20250919192904220](pic/image-20250919192904220-20260428153445-goo0kzb.png) - -### 2.2.3、编译 - -- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 -- 步骤0:使能HNR,把smp/a55_linux/mpp/sample/common/sdk_module_init.h头文件中的宏定义INIT_PQP修改为1; **(如果是其他案例,请一定要把这个宏还原为0)** - -![image-20260104143723083](pic/image-20260104143723083-20260428153445-l23g8yt.png) - -- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -- 步骤2:使用Makefile的方式进行单编 -- 在Ubuntu的命令行终端,分步执行下面的命令,单编 hnr_auto -- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 - - ``` - cd pegasus/vendor/zsks/demo/hnr_auto/ - - # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - # 检查SYSROOT_PATH配置是否生效。 - echo $SYSROOT_PATH - - make LLVM=1 clean && make LLVM=1 - ``` - - ![image-20251231154825891](pic/image-20251231154825891-20260428153445-w488g38.png) - - - 在hnr_auto/out目录下,生成一个名为main的 可执行文件,如下图所示: - - ![image-20251231154851283](pic/image-20251231154851283-20260428153445-n3azwb3.png) - -### 2.2.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 - -**方式一:使用SD卡进行资料文件的拷贝** - -- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 - -![image-20221114150205685](pic/image-20221114150205685-20260428153445-9b29muk.png) - -- 步骤1:将编译后生成的可执行文件拷贝到SD卡中。 -- 步骤2:将ss928v100_clang/smp/a55_linux/mpp/sample/hnr/目录下的cfg模型文件拷贝到SD卡中。 - -![image-20251030144458528](pic/image-20251030144458528-20260428153445-nwggobf.png) - -- 步骤3:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 - -![image](pic/image-20260428150712-7avg3km.png) - -- 在开发板的终端,执行下面的命令进行SD卡的挂载 - - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) - -```shell -mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 -``` - -- 挂载成功后,如下图所示: - -![image-20251030150209706](pic/image-20251030150209706-20260428153445-6f5qg17.png) - -**方式二:使用NFS挂载的方式进行资料文件的拷贝** - -- 首先需要自己准备一根网线 -- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -- 步骤2:将编译后生成的可执行文件拷贝到Windows的nfs共享路径下 -- 步骤2:将ss928v100_clang/smp/a55_linux/mpp/sample/hnr/目录下的cfg模型文件拷贝到Windows的nfs共享路径下 - -![image-20251030144417819](pic/image-20251030144417819-20260428153445-jt5f58c.png) - -- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 - - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 - -``` -ifconfig eth0 192.168.100.100 - -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251030150312214](pic/image-20251030150312214-20260428153445-g0j4h6x.png) - -### 2.2.5、硬件连接 - -- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 - -![image](pic/image-20260428151316-vwbp8qg.png) - -- 将摄像头与sensor板进行连接,然后将sensor板接在zsks开发板上(注意:本案例使用的sensor是OS04A10,如果你使用其他的sensor,请先修改Makefile里面的SENSOR0_TYPE,然后再重新编译一遍即可) - -![image](pic/image-20260428170537-32ijztb.png) - -### 2.2.6、功能验证 - -- 在开发板的终端执行下面的命令,运行可执行文件 - -``` -cd /mnt/demo_ohos/hnr_auto - -chmod +x ./out/main - -./out/main 0 -``` - -![image-20251030150411696](pic/image-20251030150411696-20260428153445-6f0mbgv.png) - -- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -![image](pic/image-20260428151528-smzz9s8.png) - -- 如果您看到的现象和下图现象不一致,可以确认一下镜头盖是否未取下来。 -- 如果您看到的画面是非常模糊的,您可以尝试左右拧动镜头,进行手动对焦,直到画面清晰。 -- 当我们把摄像头置于暗光环境下,当ISO值达到一定阈值后,就会调用AIISP的HNR模型,使得在暗光条件下也能看清画面。 -- HNR关闭状态 - - ![image-20250919194128847](pic/image-20250919194128847-20260428153445-1h8dz4s.png) -- HNR打开状态 - -![image-20250919194305216](pic/image-20250919194305216-20260428153445-4c4kto8.png) - -- 敲两下回传,即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310-20260428153445-ejxtxqc.png) +# 3.2、hnr_auto操作指导 + +### 3.2.1、hnr_auto程序简介 + +- hnr_auto 基于SS928V100平台开发,以zsks套件为例,hnr_auto 是基于海思的hnr案例,实现夜间超微光的功能,当外接ISO到达一定阈值是,自动切换到hnr模型,使得在黑暗条件下也能清楚看到画面。 + +### 3.2.2、目录 + +```shell +pegasus/vendor/zsks/demo/hnr_auto +|── Makefile # 编译脚本 +|── readme.txt # hnr的操作说明 +└──hnr_auto.c # hnr_auto业务代码 +``` + +### 3.2.3、编译 + +- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 +- 步骤0:使能HNR,把smp/a55_linux/mpp/sample/common/sdk_module_init.h头文件中的宏定义INIT_PQP修改为1; **(如果是其他案例,请一定要把这个宏还原为0)** + +![image-20260104143723083](pic/image-20260104143723083-20260428153445-l23g8yt.png) + +- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 +- 步骤2:使用Makefile的方式进行单编 +- 在Ubuntu的命令行终端,分步执行下面的命令,单编 hnr_auto +- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + + ``` + cd pegasus/vendor/zsks/demo/hnr_auto/ + + # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 + export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + # 检查SYSROOT_PATH配置是否生效。 + echo $SYSROOT_PATH + + make LLVM=1 clean && make LLVM=1 + ``` + + - 在hnr_auto/out目录下,生成一个名为main的 可执行文件,如下图所示: + + ![image-20251231154851283](pic/image-20251231154851283-20260428153445-n3azwb3.png) + +### 3.2.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +- 步骤1:将编译后生成的可执行文件拷贝到SD卡中。 +- 步骤2:将ss928v100_clang/smp/a55_linux/mpp/sample/hnr/目录下的cfg模型文件拷贝到SD卡中。 + +![image-20251030144458528](pic/image-20251030144458528-20260428153445-nwggobf.png) + +- 步骤3:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +![image](pic/image-20260428150712-7avg3km.png) + +- 在开发板的终端,执行下面的命令进行SD卡的挂载 + - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +- 挂载成功后,如下图所示: + +![image-20251030150209706](pic/image-20251030150209706-20260428153445-6f5qg17.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +- 首先需要自己准备一根网线 +- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +- 步骤2:将编译后生成的可执行文件拷贝到Windows的nfs共享路径下 +- 步骤2:将ss928v100_clang/smp/a55_linux/mpp/sample/hnr/目录下的cfg模型文件拷贝到Windows的nfs共享路径下 + +![image-20251030144417819](pic/image-20251030144417819-20260428153445-jt5f58c.png) + +- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + +``` +ifconfig eth0 192.168.100.100 + +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251030150312214](pic/image-20251030150312214-20260428153445-g0j4h6x.png) + +### 3.2.5、硬件连接 + +- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image](pic/image-20260428151316-vwbp8qg.png) + +- 将摄像头与sensor板进行连接,然后将sensor板接在zsks开发板上(注意:本案例使用的sensor是OS04A10,如果你使用其他的sensor,请先修改Makefile里面的SENSOR0_TYPE,然后再重新编译一遍即可) + +![image](pic/image-20260428170537-32ijztb.png) + +### 3.2.6、功能验证 + +- 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt/demo_ohos/hnr_auto + +chmod +x ./out/main + +./out/main 0 +``` + +- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +![image](pic/image-20260428151528-smzz9s8.png) + +- 如果您看到的现象和下图现象不一致,可以确认一下镜头盖是否未取下来。 +- 如果您看到的画面是非常模糊的,您可以尝试左右拧动镜头,进行手动对焦,直到画面清晰。 +- 当我们把摄像头置于暗光环境下,当ISO值达到一定阈值后,就会调用AIISP的HNR模型,使得在暗光条件下也能看清画面。 +- HNR关闭状态 + + ![image-20250919194128847](pic/image-20250919194128847-20260428153445-1h8dz4s.png) +- HNR打开状态 + +![image-20250919194305216](pic/image-20250919194305216-20260428153445-4c4kto8.png) + +- 敲两下回传,即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310-20260428153445-ejxtxqc.png) diff --git a/vendor/zsks/demo/hnr_auto/pic/desktop.ini b/vendor/zsks/demo/hnr_auto/pic/desktop.ini old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20221114150205685-20260428153445-9b29muk.png b/vendor/zsks/demo/hnr_auto/pic/image-20221114150205685-20260428153445-9b29muk.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20250919151519310-20260428153445-ejxtxqc.png b/vendor/zsks/demo/hnr_auto/pic/image-20250919151519310-20260428153445-ejxtxqc.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20250919192904220-20260428153445-goo0kzb.png b/vendor/zsks/demo/hnr_auto/pic/image-20250919192904220-20260428153445-goo0kzb.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20250919194128847-20260428153445-1h8dz4s.png b/vendor/zsks/demo/hnr_auto/pic/image-20250919194128847-20260428153445-1h8dz4s.png old mode 100755 new mode 100644 index 53cfad04c5880acffb06d7fe23eae057bb5c36c4..8abb913fbdbf13bf72f02c7fef81459b34eea630 Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20250919194128847-20260428153445-1h8dz4s.png and b/vendor/zsks/demo/hnr_auto/pic/image-20250919194128847-20260428153445-1h8dz4s.png differ diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20250919194305216-20260428153445-4c4kto8.png b/vendor/zsks/demo/hnr_auto/pic/image-20250919194305216-20260428153445-4c4kto8.png old mode 100755 new mode 100644 index 0aebb9016538c88d3250ed9d379384c2212578c6..19521b9a90d3802e9c77e97e6608e784b7ad9bd6 Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20250919194305216-20260428153445-4c4kto8.png and b/vendor/zsks/demo/hnr_auto/pic/image-20250919194305216-20260428153445-4c4kto8.png differ diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251030144417819-20260428153445-jt5f58c.png b/vendor/zsks/demo/hnr_auto/pic/image-20251030144417819-20260428153445-jt5f58c.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251030144458528-20260428153445-nwggobf.png b/vendor/zsks/demo/hnr_auto/pic/image-20251030144458528-20260428153445-nwggobf.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251030150209706-20260428153445-6f5qg17.png b/vendor/zsks/demo/hnr_auto/pic/image-20251030150209706-20260428153445-6f5qg17.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251030150312214-20260428153445-g0j4h6x.png b/vendor/zsks/demo/hnr_auto/pic/image-20251030150312214-20260428153445-g0j4h6x.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251030150411696-20260428153445-6f0mbgv.png b/vendor/zsks/demo/hnr_auto/pic/image-20251030150411696-20260428153445-6f0mbgv.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251231154825891-20260428153445-w488g38.png b/vendor/zsks/demo/hnr_auto/pic/image-20251231154825891-20260428153445-w488g38.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20251231154851283-20260428153445-n3azwb3.png b/vendor/zsks/demo/hnr_auto/pic/image-20251231154851283-20260428153445-n3azwb3.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20260104143723083-20260428153445-l23g8yt.png b/vendor/zsks/demo/hnr_auto/pic/image-20260104143723083-20260428153445-l23g8yt.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/hnr_auto/pic/image-20260428150712-7avg3km.png old mode 100755 new mode 100644 index df435036941a44a6cb7417ceb227de759f7b23b7..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20260428150712-7avg3km.png and b/vendor/zsks/demo/hnr_auto/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20260428151316-vwbp8qg.png b/vendor/zsks/demo/hnr_auto/pic/image-20260428151316-vwbp8qg.png old mode 100755 new mode 100644 index 15f31ab2465ae782b7f989394636f63afb3adf56..d9685f02d7410d1873f90b5b2cc0280f159f26aa Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20260428151316-vwbp8qg.png and b/vendor/zsks/demo/hnr_auto/pic/image-20260428151316-vwbp8qg.png differ diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20260428151528-smzz9s8.png b/vendor/zsks/demo/hnr_auto/pic/image-20260428151528-smzz9s8.png old mode 100755 new mode 100644 index 77a7bef4a3847c61c98449b68dad4c61fb494d0c..5aeccc9c51038fd22fcc550a3e6c8a5039edb32e Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20260428151528-smzz9s8.png and b/vendor/zsks/demo/hnr_auto/pic/image-20260428151528-smzz9s8.png differ diff --git a/vendor/zsks/demo/hnr_auto/pic/image-20260428170537-32ijztb.png b/vendor/zsks/demo/hnr_auto/pic/image-20260428170537-32ijztb.png old mode 100755 new mode 100644 index 1f9e8aea54b0e00e8182399a903bcdd54e728efa..1428e6f705fd823b811d91f5e10397e1d453a648 Binary files a/vendor/zsks/demo/hnr_auto/pic/image-20260428170537-32ijztb.png and b/vendor/zsks/demo/hnr_auto/pic/image-20260428170537-32ijztb.png differ diff --git a/vendor/zsks/demo/hnr_auto/sample_hnr.c b/vendor/zsks/demo/hnr_auto/sample_hnr.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/Makefile b/vendor/zsks/demo/opencv_dnn/Makefile old mode 100755 new mode 100644 index 5e6991978359022feeedefc8862ab6726223b20e..2a5610e99107f37efc9cbd1620bf430cfc11d192 --- a/vendor/zsks/demo/opencv_dnn/Makefile +++ b/vendor/zsks/demo/opencv_dnn/Makefile @@ -8,7 +8,8 @@ endif # 编译所需的公共文件 include ../Makefile.param -OPENCV_PATH := $(PWD)/../../../opensource/opencv/$(COMPILE_CHAIN) +OPENSOURCE_PATH := $(PWD)/../../../opensource +OPENCV_PATH := $(OPENSOURCE_PATH)/opencv/$(COMPILE_CHAIN) # 编译后生成的可执行文件名 TARGET := main @@ -17,10 +18,9 @@ TARGET_PATH := $(PWD)/out # 编译此工程需要包含的头文件 CFLAGS += -I$(PWD) -CFLAGS += -Wno-psabi -I$(OPENCV_PATH)/include/opencv4 +CFLAGS += -Wno-psabi -I$(OPENCV_PATH)/include/opencv4 -I$(OPENSOURCE_PATH)/log_lib CFLAGS += -fcommon CXXFLAGS += -fcommon - # 编译此工程需要依赖的.c或.cpp文件 SMP_SRCS += $(wildcard $(PWD)/*.c) @@ -31,7 +31,21 @@ CXX_SRCS += $(PWD)/main.cpp CFLAGS += -O3 -g -Wall -DUSE_USB_CAMERA CFLAGS += -fstack-protector-strong MPI_LIBS += -L$(OPENCV_PATH)/lib -MPI_LIBS += -lopencv_world +MPI_LIBS += -lopencv_calib3d +MPI_LIBS += -lopencv_core +MPI_LIBS += -lopencv_dnn +MPI_LIBS += -lopencv_features2d +MPI_LIBS += -lopencv_flann +MPI_LIBS += -lopencv_gapi +MPI_LIBS += -lopencv_highgui +MPI_LIBS += -lopencv_imgcodecs +MPI_LIBS += -lopencv_imgproc +MPI_LIBS += -lopencv_ml +MPI_LIBS += -lopencv_objdetect +MPI_LIBS += -lopencv_photo +MPI_LIBS += -lopencv_stitching +MPI_LIBS += -lopencv_video +MPI_LIBS += -lopencv_videoio # 编译工程所需的mk文件 diff --git a/vendor/zsks/demo/opencv_dnn/README.md b/vendor/zsks/demo/opencv_dnn/README.md old mode 100755 new mode 100644 index f10450c0827cf2ea4e55e6175dfb4af5e2d73632..492399a9707d580c6ead88f7f28e8efbb34fa945 --- a/vendor/zsks/demo/opencv_dnn/README.md +++ b/vendor/zsks/demo/opencv_dnn/README.md @@ -1,146 +1,141 @@ -# 2.1、opencv_dnn操作指导 - -# 2.1.1、opencv_dnn程序简介 - -- opencv_dnn sample基于SS928V100平台开发,以zsks套件为例,opencv_dnn sample是通过USB camera采集到的图片送到人脸检测模型进行推理,将得到的结果通过HDMI,显示在外接显示屏上面。 -- opencv_dnn案例,模型推理是在CPU上实现了,没有调用svp_npu的接口,都是调用opencv的接口来实现。 - -# 2.1.2、目录 - -```shell -pegasus/vendor/zsks/demo/opencv_dnn -|── media_vdec.c # 主要是将推理的结果在HDMI外接显示器上显示 -|── media_vdec.h -|── Makefile # 编译脚本 -|── main.cpp # opencv_dnn sample业务代码 -|── host_uvc.c #参考海思SDK的host_uvc代码 -└── host_uvc.h -``` - -![image-20250919181207847](pic/image-20250919181207847-20260428155154-uzwemxm.png) - -- 请在opencv_dnn目录下创建一个onnx的文件夹,然后访问链接下载[onnx模型](https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx),并放入onnx目录下 - -![image-20251015164912907](pic/image-20251015164912907-20260428155154-2xsyked.png) - -![image-20251015165024778](pic/image-20251015165024778-20260428155154-q7q5nwd.png) - -# 2.1.3、编译 - -- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 -- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -- 步骤2:使用Makefile的方式进行单编 -- 在Ubuntu的命令行终端,分步执行下面的命令,单编 opencv_dnn sample -- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 - - ``` - cd pegasus/vendor/zsks/demo/opencv_dnn - - # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - # 检查SYSROOT_PATH配置是否生效。 - echo $SYSROOT_PATH - - make LLVM=1 clean && make LLVM=1 - ``` - - - 在opencv_dnn/out目录下,生成一个名为main的可执行文件,如下图所示: - - ![image-20251231154118407](pic/image-20251231154118407-20260428155154-wuxs2ae.png) - -![image-20251231154144577](pic/image-20251231154144577-20260428155154-2v7swub.png) - -# 2.1.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 - -**方式一:使用SD卡进行资料文件的拷贝** - -- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 - -![image-20221114150205685](pic/image-20221114150205685-20260428155154-4qvikeh.png) - -- 步骤1:将编译后生成的可执行文件、onnx模型文件、opencv的lib文件都拷贝到SD卡中。 - -![image-20251023112130092](pic/image-20251023112130092-20260428155154-cqh1n3p.png) - -- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 - -![image](pic/image-20260428150712-7avg3km.png) - -- 在开发板的终端,执行下面的命令进行SD卡的挂载 - - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) - -```shell -mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 -``` - -- 挂载成功后,如下图所示: - -![image-20251023112228717](pic/image-20251023112228717-20260428155154-6u098o8.png) - -**方式二:使用NFS挂载的方式进行资料文件的拷贝** - -- 首先需要自己准备一根网线 -- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -- 步骤2:将编译后生成的可执行文件、onnx模型文件、opencv库(在pegasus/vendor/opensource/opencv/lib目录下)都拷贝到Windows的nfs共享路径下 - -![image-20251023112328619](pic/image-20251023112328619-20260428155154-wc95wvm.png) - -- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 - - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 - -``` -ifconfig eth0 192.168.100.100 - -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251023112352692](pic/image-20251023112352692-20260428155154-c4gqzws.png) - -# 2.1.5、硬件连接 - -- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 - -![image](pic/image-20260428151316-vwbp8qg.png) - -- 将USB 摄像头接在EulerPi开发板的USB接口上。 - -![image](pic/image-20260428151432-6nzax2h.png) - -# 2.1.6、功能验证 - -- 在开发板的终端执行下面的命令,运行可执行文件 - -```c -# 把opencv的库添加到环境变量中 -export LD_LIBRARY_PATH=/mnt/demo_ohos/opencv_dnn/lib:$LD_LIBRARY_PATH - -cd /mnt/demo_ohos/opencv_dnn/lib - -ln -s libopencv_world.so libopencv_world.so.413 - -cd /mnt/demo_ohos/opencv_dnn - - -chmod +x ./out/main - -./out/main /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg -``` - -![image-20251023112451423](pic/image-20251023112451423-20260428155154-jeei5hl.png) - -- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -![image](pic/image-20260428151528-smzz9s8.png) - -- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 - -![image-20250919151018659](pic/image-20250919151018659-20260428155154-hmsqk38.png) - -- 正常情况下,我们会在外接显示屏上看到有人脸的区域被框出来,且在框框的左上角显示置信度。 - -![image-20250919183224310](pic/image-20250919183224310-20260428155154-m30s86i.png) - -- Ctrl + C,然后回车即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310-20260428155154-pcw91eu.png) +# 3.1、opencv_dnn操作指导 + +# 3.1.1、opencv_dnn程序简介 + +- opencv_dnn sample基于SS928V100平台开发,以zsks套件为例,opencv_dnn sample是通过USB camera采集到的图片送到人脸检测模型进行推理,将得到的结果通过HDMI,显示在外接显示屏上面。 +- opencv_dnn案例,模型推理是在CPU上实现了,没有调用svp_npu的接口,都是调用opencv的接口来实现。 + +# 3.1.2、目录 + +```shell +pegasus/vendor/zsks/demo/opencv_dnn +|── media_vdec.c # 主要是将推理的结果在HDMI外接显示器上显示 +|── media_vdec.h +|── Makefile # 编译脚本 +|── main.cpp # opencv_dnn sample业务代码 +|── host_uvc.c #参考海思SDK的host_uvc代码 +└── host_uvc.h +``` + +- 请在opencv_dnn目录下创建一个onnx的文件夹,然后访问链接下载[onnx模型](https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx),并放入onnx目录下 + +![image-20251015164912907](pic/image-20251015164912907-20260428155154-2xsyked.png) + +![image-20251015165024778](pic/image-20251015165024778-20260428155154-q7q5nwd.png) + +# 3.1.3、编译 + +- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 +- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 +- 步骤2:使用Makefile的方式进行单编 +- 在Ubuntu的命令行终端,分步执行下面的命令,单编 opencv_dnn sample +- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + + ``` + cd pegasus/vendor/zsks/demo/opencv_dnn + + # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 + export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + # 检查SYSROOT_PATH配置是否生效。 + echo $SYSROOT_PATH + + make LLVM=1 clean && make LLVM=1 + ``` + + - 在opencv_dnn/out目录下,生成一个名为main的可执行文件,如下图所示: + + +![image-20251231154144577](pic/image-20251231154144577-20260428155154-2v7swub.png) + +# 3.1.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +![image-20221114150205685](pic/image-20221114150205685-20260428155154-4qvikeh.png) + +- 步骤1:将编译后生成的可执行文件、onnx模型文件、opencv的lib文件都拷贝到SD卡中。 + +![image-20251023112130092](pic/image-20251023112130092-20260428155154-cqh1n3p.png) + +- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +![image](pic/image-20260428150712-7avg3km.png) + +- 在开发板的终端,执行下面的命令进行SD卡的挂载 + - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +- 挂载成功后,如下图所示: + +![image-20251023112228717](pic/image-20251023112228717-20260428155154-6u098o8.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +- 首先需要自己准备一根网线 +- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +- 步骤2:将编译后生成的可执行文件、onnx模型文件、opencv库(在pegasus/vendor/opensource/opencv/lib目录下)都拷贝到Windows的nfs共享路径下 + +![image-20251023112328619](pic/image-20251023112328619-20260428155154-wc95wvm.png) + +- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + +``` +ifconfig eth0 193.168.100.100 + +mount -o nolock,addr=193.168.100.10 -t nfs 193.168.100.10:/d/nfs /mnt +``` + +![image-20251023112352692](pic/image-20251023112352692-20260428155154-c4gqzws.png) + +# 3.1.5、硬件连接 + +- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image](pic/image-20260428151316-vwbp8qg.png) + +- 将USB 摄像头接在EulerPi开发板的USB接口上。 + +![image](pic/image-20260428151432-6nzax2h.png) + +# 3.1.6、功能验证 + +- 在开发板的终端执行下面的命令,运行可执行文件 + +```c +# 把opencv的库添加到环境变量中 +export LD_LIBRARY_PATH=/mnt/demo_ohos/opencv_dnn/lib:$LD_LIBRARY_PATH + +cd /mnt/demo_ohos/opencv_dnn/lib + +ln -s libopencv_world.so libopencv_world.so.413 + +cd /mnt/demo_ohos/opencv_dnn + + +chmod +x ./out/main + +./out/main /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg +``` + +- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +![image](pic/image-20260428151528-smzz9s8.png) + +- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659-20260428155154-hmsqk38.png) + +- 正常情况下,我们会在外接显示屏上看到有人脸的区域被框出来,且在框框的左上角显示置信度。 + +![image-20250919183224310](pic/image-20250919183224310-20260428155154-m30s86i.png) + +- Ctrl + C,然后回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310-20260428155154-pcw91eu.png) diff --git a/vendor/zsks/demo/opencv_dnn/host_uvc.c b/vendor/zsks/demo/opencv_dnn/host_uvc.c old mode 100755 new mode 100644 index ee4620bdfdfcf0dd790ddd675b4f008e15a46ef2..6b13c3fcdadaa7fd1d5efe716e29a34537a9d91b --- a/vendor/zsks/demo/opencv_dnn/host_uvc.c +++ b/vendor/zsks/demo/opencv_dnn/host_uvc.c @@ -16,14 +16,13 @@ * * Modifications Author: yaohongtao (yht@cust.edu.cn) */ -#include +#include "host_uvc.h" +#include #include -#include -#include +#include #include -#include #include -#include "host_uvc.h" +#include #ifdef __cplusplus #if __cplusplus @@ -31,30 +30,44 @@ extern "C" { #endif #endif -#define array_size(a) (sizeof(a) / sizeof((a)[0])) +#define UVC_DEFAULT_WIDTH 640 +#define UVC_DEFAULT_HEIGHT 480 +#define FOURCC_CHAR_COUNT 4 +#define FOURCC_NAME_BUF_SIZE 5 +#define FOURCC_BYTE_SHIFT 8 +#define FOURCC_SHIFT_SECOND_BYTE 16 +#define FOURCC_SHIFT_THIRD_BYTE 24 +#define FOURCC_BYTE_MASK 0xff +#define STRTOL_BASE_DECIMAL 10 +#define GETOPT_ARG_OPTIONAL 2 +#define GETOPT_ARG_REQUIRED 1 +#define GETOPT_ARG_NONE 0 format_info g_pixel_formats[] = { - { "YUYV", V4L2_PIX_FMT_YUYV, 1 }, - { "MJPEG", V4L2_PIX_FMT_MJPEG, 1 }, - { "H264", V4L2_PIX_FMT_H264, 1 }, - { "H265", V4L2_PIX_FMT_H265, 1 }, - { "NV12", V4L2_PIX_FMT_NV12, 1 }, - { "NV21", V4L2_PIX_FMT_NV21, 1 }, + {"YUYV", V4L2_PIX_FMT_YUYV, 1}, + {"MJPEG", V4L2_PIX_FMT_MJPEG, 1}, + {"H264", V4L2_PIX_FMT_H264, 1}, + {"H265", V4L2_PIX_FMT_H265, 1}, + {"NV12", V4L2_PIX_FMT_NV12, 1}, + {"NV21", V4L2_PIX_FMT_NV21, 1}, }; -static struct option g_opts[] = { - {"file", 2, 0, 'F'}, /* 2 is a number */ - {"format", 1, 0, 'f'}, - {"help", 0, 0, 'h'}, - {"size", 1, 0, 's'}, - {0, 0, 0, 0} -}; +static td_u32 sample_uvc_pixel_format_count(td_void) +{ + return (td_u32)(sizeof(g_pixel_formats) / sizeof(g_pixel_formats[0])); +} -static const format_info *sample_uvc_v4l2_format_by_fourcc(td_u32 fourcc) +static struct option g_opts[] = {{"file", GETOPT_ARG_OPTIONAL, GETOPT_ARG_NONE, 'F'}, + {"format", GETOPT_ARG_REQUIRED, GETOPT_ARG_NONE, 'f'}, + {"help", GETOPT_ARG_NONE, GETOPT_ARG_NONE, 'h'}, + {"size", GETOPT_ARG_REQUIRED, GETOPT_ARG_NONE, 's'}, + {0, GETOPT_ARG_NONE, GETOPT_ARG_NONE, 0}}; + +static const format_info* sample_uvc_v4l2_format_by_fourcc(td_u32 fourcc) { td_u32 i; - for (i = 0; i < array_size(g_pixel_formats); ++i) { + for (i = 0; i < sample_uvc_pixel_format_count(); ++i) { if (g_pixel_formats[i].fourcc == fourcc) { return &g_pixel_formats[i]; } @@ -62,7 +75,7 @@ static const format_info *sample_uvc_v4l2_format_by_fourcc(td_u32 fourcc) return TD_NULL; } -static td_void sample_uvc_usage(const td_char *argv0) +static td_void sample_uvc_usage(const td_char* argv0) { printf("sample_uvc_usage: %s device [options]\n", argv0); printf("supported options:\n"); @@ -70,20 +83,19 @@ static td_void sample_uvc_usage(const td_char *argv0) printf("-F, --file[=name] write file\n"); printf("-h, --help show help info\n"); printf("-s, --size WxH set the frame size (eg. 1920x1080)\n\n"); - printf("inquire USB device format: ./sample_uvc --enum-formats\n\n"); printf("example of setting USB device format:\n"); - printf(" ./opencv_dnn /dev/media0 -fH264 -s1920x1080 -Ftest.h264\n"); - printf(" ./opencv_dnn /dev/media0 -fH265 -s1920x1080 -Ftest.h265\n"); - printf(" ./opencv_dnn /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg\n"); - printf(" ./opencv_dnn /dev/media0 -fYUYV -s1920x1080 -Ftest.yuv\n"); - printf(" ./opencv_dnn /dev/media0 -fNV21 -s640x360 -Ftest.yuv\n\n"); + printf(" ./main /dev/media0 -fH264 -s1920x1080 -Ftest.h264\n"); + printf(" ./main /dev/media0 -fH265 -s1920x1080 -Ftest.h265\n"); + printf(" ./main /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg\n"); + printf(" ./main /dev/media0 -fYUYV -s1920x1080 -Ftest.yuv\n"); + printf(" ./main /dev/media0 -fNV21 -s640x360 -Ftest.yuv\n\n"); printf("note: set macro MEDIA_WORK to 0 to write file on disk.\n\n"); } -static const format_info *sample_uvc_v4l2_format_by_name(const td_char *name) +static const format_info* sample_uvc_v4l2_format_by_name(const td_char* name) { td_u32 i; - for (i = 0; i < array_size(g_pixel_formats); ++i) { + for (i = 0; i < sample_uvc_pixel_format_count(); ++i) { if (!strcmp(g_pixel_formats[i].name, name)) { return &g_pixel_formats[i]; } @@ -94,93 +106,97 @@ static const format_info *sample_uvc_v4l2_format_by_name(const td_char *name) static td_void sample_uvc_list_formats(td_void) { td_u32 i; - for (i = 0; i < array_size(g_pixel_formats); i++) { - sample_print("%s (\"%c%c%c%c\", %u planes)\n", g_pixel_formats[i].name, g_pixel_formats[i].fourcc & 0xff, - (g_pixel_formats[i].fourcc >> 8) & 0xff, (g_pixel_formats[i].fourcc >> 16) & 0xff, /* 8,16:shift */ - (g_pixel_formats[i].fourcc >> 24) & 0xff, g_pixel_formats[i].n_planes); /* 24:shift */ + for (i = 0; i < sample_uvc_pixel_format_count(); i++) { + sample_print("%s (\"%c%c%c%c\", %u planes)\n", + g_pixel_formats[i].name, + g_pixel_formats[i].fourcc & FOURCC_BYTE_MASK, + (g_pixel_formats[i].fourcc >> FOURCC_BYTE_SHIFT) & FOURCC_BYTE_MASK, + (g_pixel_formats[i].fourcc >> FOURCC_SHIFT_SECOND_BYTE) & FOURCC_BYTE_MASK, + (g_pixel_formats[i].fourcc >> FOURCC_SHIFT_THIRD_BYTE) & FOURCC_BYTE_MASK, + g_pixel_formats[i].n_planes); } } -static td_s32 sample_uvc_get_opt(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info) +static td_s32 sample_uvc_get_opt(td_s32 argc, td_char* argv[], uvc_ctrl_info* ctrl_info) { td_s32 c; - const format_info *info; - td_char *endptr; + const format_info* info; + td_char* endptr; while ((c = getopt_long(argc, argv, "B:c::Cd:f:F::hi:Iln:p::q:r:R::s:t:uw:x:", g_opts, TD_NULL)) != -1) { switch (c) { - case 'f': - if (!strcmp("help", optarg)) { - sample_uvc_list_formats(); - return TD_FAILURE; - } - ctrl_info->do_set_format = 1; - info = sample_uvc_v4l2_format_by_name(optarg); - if (info == TD_NULL) { - sample_print("Unsupported video format '%s'\n", optarg); - return TD_FAILURE; - } - ctrl_info->pixelformat = info->fourcc; - break; - case 'F': - ctrl_info->do_file = 1; - if (optarg) { - ctrl_info->pattern = optarg; - } - break; - case 'h': - sample_uvc_usage(argv[0]); + case 'f': + if (!strcmp("help", optarg)) { + sample_uvc_list_formats(); + return TD_FAILURE; + } + ctrl_info->do_set_format = 1; + info = sample_uvc_v4l2_format_by_name(optarg); + if (info == TD_NULL) { + sample_print("Unsupported video format '%s'\n", optarg); return TD_FAILURE; - case 's': - ctrl_info->do_capture = 1; - ctrl_info->do_set_format = 1; - ctrl_info->width = strtol(optarg, &endptr, 10); /* 10:base */ - if (*endptr != 'x' || endptr == optarg) { - sample_print("Invalid size '%s'\n", optarg); - return TD_FAILURE; - } - ctrl_info->height = strtol(endptr + 1, &endptr, 10); /* 10:base */ - if (*endptr != 0) { - sample_print("Invalid size '%s'\n", optarg); - return TD_FAILURE; - } - break; - default: - sample_print("Run %s -h for help.\n", argv[0]); + } + ctrl_info->pixelformat = info->fourcc; + break; + case 'F': + ctrl_info->do_file = 1; + if (optarg) { + ctrl_info->pattern = optarg; + } + break; + case 'h': + sample_uvc_usage(argv[0]); + return TD_FAILURE; + case 's': + ctrl_info->do_capture = 1; + ctrl_info->do_set_format = 1; + ctrl_info->width = strtol(optarg, &endptr, STRTOL_BASE_DECIMAL); + if (*endptr != 'x' || endptr == optarg) { + sample_print("Invalid size '%s'\n", optarg); return TD_FAILURE; + } + ctrl_info->height = strtol(endptr + 1, &endptr, STRTOL_BASE_DECIMAL); + if (*endptr != 0) { + sample_print("Invalid size '%s'\n", optarg); + return TD_FAILURE; + } + break; + default: + sample_print("Run %s -h for help.\n", argv[0]); + return TD_FAILURE; } } return TD_SUCCESS; } -static td_void sample_uvc_ctrl_info_init(uvc_ctrl_info *ctrl_info) +static td_void sample_uvc_ctrl_info_init(uvc_ctrl_info* ctrl_info) { ctrl_info->pattern = "frame-#.bin"; - ctrl_info->width = 640; /* 640:width */ - ctrl_info->height = 480; /* 480:height */ + ctrl_info->width = UVC_DEFAULT_WIDTH; + ctrl_info->height = UVC_DEFAULT_HEIGHT; ctrl_info->pixelformat = V4L2_PIX_FMT_YUYV; } -const td_char *sample_uvc_v4l2_format_name(td_u32 fourcc) +const td_char* sample_uvc_v4l2_format_name(td_u32 fourcc) { - const format_info *format; - static td_char format_name[5]; /* 5: array len */ + const format_info* format; + static td_char format_name[FOURCC_NAME_BUF_SIZE]; td_u32 i; format = sample_uvc_v4l2_format_by_fourcc(fourcc); if (format) { return format->name; } - for (i = 0; i < 4; ++i) { /* 4: format */ - format_name[i] = fourcc & 0xff; - fourcc >>= 8; /* 8: shift */ + for (i = 0; i < FOURCC_CHAR_COUNT; ++i) { + format_name[i] = fourcc & FOURCC_BYTE_MASK; + fourcc >>= FOURCC_BYTE_SHIFT; } - format_name[4] = '\0'; /* 4: end */ + format_name[FOURCC_CHAR_COUNT] = '\0'; return format_name; } -td_s32 sample_host_uvc(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info) +td_s32 sample_host_uvc(td_s32 argc, td_char* argv[], uvc_ctrl_info* ctrl_info) { int ret; sample_uvc_ctrl_info_init(ctrl_info); @@ -192,7 +208,7 @@ td_s32 sample_host_uvc(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info) sample_uvc_usage(argv[0]); return TD_FAILURE; } - return TD_SUCCESS ; + return TD_SUCCESS; } #ifdef __cplusplus diff --git a/vendor/zsks/demo/opencv_dnn/host_uvc.h b/vendor/zsks/demo/opencv_dnn/host_uvc.h old mode 100755 new mode 100644 index 2260d03101ecb6a09ad12f938aca663b297f8059..15d25a49ea9311402046a782f0fe60f8433ec743 --- a/vendor/zsks/demo/opencv_dnn/host_uvc.h +++ b/vendor/zsks/demo/opencv_dnn/host_uvc.h @@ -16,10 +16,10 @@ #ifndef __HOST_UVC_H__ #define __HOST_UVC_H__ -#include -#include -#include #include "sample_comm.h" +#include +#include +#include #ifdef __cplusplus #if __cplusplus extern "C" { @@ -27,18 +27,18 @@ extern "C" { #endif #ifndef V4L2_PIX_FMT_H265 -#define V4L2_PIX_FMT_H265 v4l2_fourcc('H', '2', '6', '5') /* H.265 aka HEVC */ +#define V4L2_PIX_FMT_H265 v4l2_fourcc('H', '2', '6', '5') /* H.265 aka HEVC */ #endif typedef struct { - const td_char *name; + const td_char* name; td_u32 fourcc; td_char n_planes; } format_info; typedef struct { - const td_char *pattern; - const td_char *type_name; + const td_char* pattern; + const td_char* type_name; td_s32 do_capture; td_s32 do_set_format; td_u32 pixelformat; @@ -48,8 +48,8 @@ typedef struct { td_u32 height; } uvc_ctrl_info; -td_s32 sample_host_uvc(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info); -const td_char *sample_uvc_v4l2_format_name(td_u32 fourcc); +td_s32 sample_host_uvc(td_s32 argc, td_char* argv[], uvc_ctrl_info* ctrl_info); +const td_char* sample_uvc_v4l2_format_name(td_u32 fourcc); #ifdef __cplusplus #if __cplusplus diff --git a/vendor/zsks/demo/opencv_dnn/main.cpp b/vendor/zsks/demo/opencv_dnn/main.cpp old mode 100755 new mode 100644 index 7f2b4549de6d3d9133baaffd4e66071fd7b7c303..8583bd0452d742f40c6a69e454448fadd175ec15 --- a/vendor/zsks/demo/opencv_dnn/main.cpp +++ b/vendor/zsks/demo/opencv_dnn/main.cpp @@ -19,33 +19,128 @@ * Email: yht@cust.edu.cn */ -#include -#include +#include "host_uvc.h" +#include "media_vdec.h" #include +#include +#include #include +#include #include -#include -#include +#include +#include #include -#include -#include -#include -#include "host_uvc.h" -#include "media_vdec.h" -#include "sdk_module_init.h" +#include +#include using namespace cv; using namespace std; using namespace std::chrono; -td_bool g_uvc_exit = TD_FALSE; +struct camera_params { + VideoCapture *cap; + int width; + int height; + int fps; + const char *type_name; + int *retry_count; +}; + +struct app_config { + int width; + int height; + int fps; + const char *type_name; +}; + +struct performance_data { + int frame_count; + double elapsed_sec; + double total_frame_time; + double total_detect_time; + double total_encode_time; + const vector *frame_times; +}; + +struct processing_state { + int retry_count = 0; + bool device_reconnected = false; + int empty_frame_count = 0; + Mat frame; + Mat yuv_frame; + vector mjpeg_buffer; + vector mjpeg_params; + ot_size pic_size; + int frame_count = 0; + vector last_detected_faces; + vector last_confidence_scores; + high_resolution_clock::time_point last_time; + int fps_frame_count = 0; + vector frame_times; + double total_frame_time = 0; + double total_detect_time = 0; + double total_encode_time = 0; +}; + +static void print_performance_stats(const performance_data &data); +static bool handle_empty_frame(camera_params &cam_params, processing_state &state); +static bool reinitialize_media_pipeline(const char *type_name, int width, int height); + +namespace { + enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, + }; + + enum class face_det_field : int { + X = 0, + Y = 1, + WIDTH = 2, + HEIGHT = 3, + SCORE = 4, + }; + + constexpr int CAMERA_DEVICE_INDEX = 0; + constexpr int DEFAULT_FPS = 30; + constexpr int CAPTURE_BUFFER_SIZE = 4; + constexpr int CPU_THREAD_COUNT = 4; + constexpr int MAX_RECONNECT_RETRIES = 3; + constexpr int MAX_EMPTY_FRAMES = 10; + constexpr int DETECT_INTERVAL_FRAMES = 5; + constexpr int MIN_FACE_SIZE_PX = 50; + constexpr int JPEG_QUALITY = 90; + constexpr int SCORE_TEXT_BUF_SIZE = 20; + constexpr int FPS_STAT_WINDOW_SIZE = 100; + constexpr int FACE_DET_INPUT_WIDTH = 256; + constexpr int FACE_DET_INPUT_HEIGHT = 144; + constexpr int FACE_DET_TOP_K = 100; + constexpr int YUV420_BUFFER_RATIO_NUM = 3; + constexpr int YUV420_BUFFER_RATIO_DEN = 2; + constexpr int RECT_LINE_THICKNESS = 2; + constexpr int TEXT_LINE_THICKNESS = 1; + constexpr int TEXT_Y_OFFSET = 5; + constexpr int STDIN_READ_BUF_SIZE = 64; + constexpr int RECONNECT_SLEEP_SEC = 1; + constexpr int COLOR_CHANNEL_MAX = 255; + constexpr int ESC_KEY_CODE = 27; + constexpr float FACE_DET_SCORE_THRESHOLD = 0.6f; + constexpr float FACE_DET_NMS_THRESHOLD = 0.7f; + constexpr double SCORE_PERCENT_DIVISOR = 100.0; + constexpr double FPS_PRINT_INTERVAL_SEC = 1.0; + constexpr double MS_PER_SECOND = 1000.0; + constexpr double TEXT_FONT_SCALE = 0.5; + + const Scalar FACE_BOX_COLOR(0, COLOR_CHANNEL_MAX, 0); +} // namespace + +td_bool g_uvcExit = TD_FALSE; class ScopeGuard { public: explicit ScopeGuard(std::function fn) : fn_(std::move(fn)) {} - ScopeGuard(const ScopeGuard&) = delete; - ScopeGuard& operator=(const ScopeGuard&) = delete; - ScopeGuard(ScopeGuard&& other) noexcept : fn_(std::move(other.fn_)), active_(other.active_) + ScopeGuard(const ScopeGuard &) = delete; + ScopeGuard &operator=(const ScopeGuard &) = delete; + ScopeGuard(ScopeGuard &&other) noexcept : fn_(std::move(other.fn_)), active_(other.active_) { other.active_ = false; } @@ -62,20 +157,19 @@ private: bool active_ = true; }; -// 优化内存管理类 class MemoryManager { public: - static void optimizeMemory() + static void optimize_memory() { cv::setUseOptimized(true); - cv::setNumThreads(4); /* 4: Number of CPU cores */ + cv::setNumThreads(CPU_THREAD_COUNT); } }; static void sample_uvc_exit_signal_handler(int signal) { printf("收到退出信号,准备退出...\n"); - g_uvc_exit = TD_TRUE; + g_uvcExit = TD_TRUE; } static bool should_exit_from_stdin() @@ -96,7 +190,7 @@ static bool should_exit_from_stdin() return false; } - char buf[64]; + char buf[STDIN_READ_BUF_SIZE]; ssize_t n = read(STDIN_FILENO, buf, sizeof(buf)); if (n <= 0) { return false; @@ -104,69 +198,39 @@ static bool should_exit_from_stdin() for (ssize_t i = 0; i < n; ++i) { const unsigned char c = static_cast(buf[i]); - if (c == '\n' || c == '\r' || c == 27 /* ESC */ || c == 'q' || c == 'Q') { + if (c == '\n' || c == '\r' || c == ESC_KEY_CODE || c == 'q' || c == 'Q') { return true; } } return false; } -int main(int argc, char** argv) +static void register_exit_signal_handlers() { - // 优化内存使用 - MemoryManager::optimizeMemory(); - - int ret; - uvc_ctrl_info ctrl_info = {0}; struct sigaction sig_exit; sig_exit.sa_handler = sample_uvc_exit_signal_handler; sig_exit.sa_flags = 0; sigemptyset(&sig_exit.sa_mask); sigaction(SIGINT, &sig_exit, nullptr); sigaction(SIGTERM, &sig_exit, nullptr); - ret = sample_host_uvc(argc, argv, &ctrl_info); - if (ret != TD_SUCCESS) { - return TD_FAILURE; - } -#ifdef CONFIG_USER_SPACE - SDK_init(); -#endif - ScopeGuard sdk_guard([] { -#ifdef CONFIG_USER_SPACE - SDK_exit(); -#endif - }); - - // OpenCV V4L2 video capture - VideoCapture cap(0, cv::CAP_V4L2); - if (!cap.isOpened()) { - printf("Error: Failed to open camera device!\n"); - return -1; - } - ScopeGuard cap_guard([&cap] { cap.release(); }); - - int width = ctrl_info.width; - int height = ctrl_info.height; - int fps = 30; +} - // 设置摄像头参数 +static bool configure_camera(VideoCapture &cap, int &width, int &height, int fps, const char *type_name) +{ cap.set(CAP_PROP_FRAME_WIDTH, width); cap.set(CAP_PROP_FRAME_HEIGHT, height); cap.set(CAP_PROP_FPS, fps); - cap.set(CAP_PROP_BUFFERSIZE, 4); /* 4: Increase buffer size */ + cap.set(CAP_PROP_BUFFERSIZE, CAPTURE_BUFFER_SIZE); - // 根据格式设置摄像头参数 - const char* type_name = sample_uvc_v4l2_format_name(ctrl_info.pixelformat); if (strcmp(type_name, "MJPEG") == 0) { cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); } else if (strcmp(type_name, "YUYV") == 0) { cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y', 'U', 'Y', 'V')); } else { std::cerr << "只支持 YUYV 或 MJPEG 格式,请用 -fYUYV 或 -fMJPEG 参数启动!" << std::endl; - return -1; + return false; } - // 验证设置是否成功 int actual_width = cap.get(CAP_PROP_FRAME_WIDTH); int actual_height = cap.get(CAP_PROP_FRAME_HEIGHT); double actual_fps = cap.get(CAP_PROP_FPS); @@ -181,198 +245,348 @@ int main(int argc, char** argv) height = actual_height; } - // 初始化人脸检测器,使用更快的参数 - const string modelPath = "./onnx/face_detection_yunet_2023mar.onnx"; - Ptr detector = FaceDetectorYN::create( - /* 256 144 input width height 0.6 score_threshold 0.7 nms_threshold */ - modelPath, "", Size(256, 144), 0.6, 0.7, 100); /* 100 top_k */ - if (!detector) { - printf("Error: Failed to create face detector\n"); - return -1; + return true; +} + +static Ptr create_face_detector() +{ + const string model_path = "./onnx/face_detection_yunet_2023mar.onnx"; + return FaceDetectorYN::create(model_path, "", Size(FACE_DET_INPUT_WIDTH, FACE_DET_INPUT_HEIGHT), + FACE_DET_SCORE_THRESHOLD, FACE_DET_NMS_THRESHOLD, FACE_DET_TOP_K); +} + +static bool reconnect_camera(camera_params ¶ms) +{ + printf("Attempting to reconnect camera (attempt %d/%d)...\n", *params.retry_count + 1, MAX_RECONNECT_RETRIES); + params.cap->release(); + sleep(RECONNECT_SLEEP_SEC); + + params.cap->open(CAMERA_DEVICE_INDEX, cv::CAP_V4L2); + if (!params.cap->isOpened()) { + (*params.retry_count)++; + printf("Retry %d/%d failed\n", *params.retry_count, MAX_RECONNECT_RETRIES); + return false; } - // 初始化媒体链路 - if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { - std::cerr << "media start failed!" << std::endl; - return -1; + params.cap->set(CAP_PROP_FRAME_WIDTH, params.width); + params.cap->set(CAP_PROP_FRAME_HEIGHT, params.height); + params.cap->set(CAP_PROP_FPS, params.fps); + params.cap->set(CAP_PROP_BUFFERSIZE, CAPTURE_BUFFER_SIZE); + if (strcmp(params.type_name, "MJPEG") == 0) { + params.cap->set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); + } else { + params.cap->set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y', 'U', 'Y', 'V')); } - ScopeGuard media_guard([] { - sample_uvc_media_stop_receive_data(); - sample_uvc_media_exit(); - }); - const int MAX_RETRIES = 3; /* 3: max retries */ - int retry_count = 0; - bool device_reconnected = false; - int empty_frame_count = 0; - const int MAX_EMPTY_FRAMES = 10; /* 10: max empty frames */ + int actual_width = params.cap->get(CAP_PROP_FRAME_WIDTH); + int actual_height = params.cap->get(CAP_PROP_FRAME_HEIGHT); + double actual_fps = params.cap->get(CAP_PROP_FPS); + + printf("Camera reconnected successfully\n"); + printf("New resolution: %dx%d @ %.2f fps\n", actual_width, actual_height, actual_fps); + + params.width = actual_width; + params.height = actual_height; + *params.retry_count = 0; + return true; +} + +static double detect_faces(const Mat &frame, const Ptr &detector, + vector &detected_faces, vector &confidence_scores) +{ + auto detect_start = high_resolution_clock::now(); + + Mat small_frame; + resize(frame, small_frame, Size(FACE_DET_INPUT_WIDTH, FACE_DET_INPUT_HEIGHT), 0, 0, INTER_NEAREST); - // 预分配Mat对象 - Mat frame; Mat faces; - Mat yuvFrame; - vector mjpeg_buffer; - mjpeg_buffer.reserve(width * height * 3 / 2); /* 3 / 2 YUV420 memory size */ + detector->detect(small_frame, faces); - // 创建MJPEG编码器 - vector mjpeg_params = { - IMWRITE_JPEG_QUALITY, 90, /* 90: JPEG quality */ - IMWRITE_JPEG_OPTIMIZE, 1, - IMWRITE_JPEG_PROGRESSIVE, 0 - }; + detected_faces.clear(); + confidence_scores.clear(); - // 预分配VPSS缓冲区 - ot_size pic_size; - pic_size.width = static_cast(width); - pic_size.height = static_cast(height); + if (faces.rows > 0) { + float scale_x = static_cast(frame.cols) / small_frame.cols; + float scale_y = static_cast(frame.rows) / small_frame.rows; + + for (int i = 0; i < faces.rows; ++i) { + int x = static_cast(faces.at(i, static_cast(face_det_field::X)) * scale_x); + int y = static_cast(faces.at(i, static_cast(face_det_field::Y)) * scale_y); + int w = static_cast(faces.at(i, static_cast(face_det_field::WIDTH)) * scale_x); + int h = static_cast(faces.at(i, static_cast(face_det_field::HEIGHT)) * scale_y); + float score = faces.at(i, static_cast(face_det_field::SCORE)); + + if (w >= MIN_FACE_SIZE_PX && h >= MIN_FACE_SIZE_PX) { + detected_faces.emplace_back(x, y, w, h); + confidence_scores.push_back(score); + } + } + } + + auto detect_end = high_resolution_clock::now(); + return duration(detect_end - detect_start).count(); +} + +static void draw_face_boxes(Mat &frame, const vector &faces, const vector &scores) +{ + for (size_t i = 0; i < faces.size(); ++i) { + rectangle(frame, faces[i], FACE_BOX_COLOR, RECT_LINE_THICKNESS); + char score_text[SCORE_TEXT_BUF_SIZE]; + int ret = snprintf(score_text, sizeof(score_text), + "Conf: %.2f", scores[i] / SCORE_PERCENT_DIVISOR); + if (ret < 0) { + printf("[func]:%s [line]:%d [info]:snprintf failed\n", __FUNCTION__, __LINE__); + break; + } + putText(frame, score_text, Point(faces[i].x, faces[i].y - TEXT_Y_OFFSET), + FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, FACE_BOX_COLOR, TEXT_LINE_THICKNESS); + } +} +static void sync_pic_size_from_frame(const Mat &frame, processing_state &state, const char *type_name) +{ + if (frame.cols != static_cast(state.pic_size.width) || + frame.rows != static_cast(state.pic_size.height)) { + state.pic_size.width = static_cast(frame.cols); + state.pic_size.height = static_cast(frame.rows); + if (strcmp(type_name, "YUYV") == 0) { + state.yuv_frame.create(frame.rows, frame.cols, CV_8UC2); + } + } +} + +static double encode_and_send_frame(Mat &frame, const char *type_name, processing_state &state) +{ + auto encode_start = high_resolution_clock::now(); + int ret = 0; + + sync_pic_size_from_frame(frame, state, type_name); + + if (strcmp(type_name, "MJPEG") == 0) { + imencode(".jpg", frame, state.mjpeg_buffer, state.mjpeg_params); + ret = sample_uvc_media_send_data(state.mjpeg_buffer.data(), state.mjpeg_buffer.size(), + frame.cols, &state.pic_size, "MJPEG"); + } else { + cv::cvtColor(frame, state.yuv_frame, cv::COLOR_BGR2YUV_YUY2); + ret = sample_uvc_media_send_data(state.yuv_frame.data, state.yuv_frame.total() * state.yuv_frame.elemSize(), + state.yuv_frame.step, &state.pic_size, "YUYV"); + } + + auto encode_end = high_resolution_clock::now(); + + if (ret != 0) { + ret = -errno; + std::cerr << "write error: " << strerror(-ret) << std::endl; + } + + return duration(encode_end - encode_start).count(); +} + +static void update_performance_stats(double frame_time, double detect_time, double encode_time, processing_state &state) +{ + state.fps_frame_count++; + state.total_frame_time += frame_time; + state.total_detect_time += detect_time; + state.total_encode_time += encode_time; + + if (state.frame_times.size() >= FPS_STAT_WINDOW_SIZE) { + state.frame_times.erase(state.frame_times.begin()); + } + state.frame_times.push_back(static_cast(frame_time)); + + auto current_time = high_resolution_clock::now(); + duration total_elapsed = current_time - state.last_time; + if (total_elapsed.count() >= FPS_PRINT_INTERVAL_SEC) { + performance_data perf_data = { + state.fps_frame_count, + total_elapsed.count(), + state.total_frame_time, + state.total_detect_time, + state.total_encode_time, + &state.frame_times + }; + print_performance_stats(perf_data); + + state.last_time = current_time; + state.fps_frame_count = 0; + state.total_frame_time = 0; + state.total_detect_time = 0; + state.total_encode_time = 0; + } +} + +static void print_performance_stats(const performance_data &data) +{ + double current_fps = data.frame_count / data.elapsed_sec; + + double avg_frame_time = 0; + for (float t : *data.frame_times) { + avg_frame_time += t; + } + if (!data.frame_times->empty()) { + avg_frame_time /= data.frame_times->size(); + } + + double avg_detect_time = data.total_detect_time / data.frame_count; + double avg_encode_time = data.total_encode_time / data.frame_count; + + printf("\rFPS: %.2f | Frame: %.0f ms | Detect: %.2f ms | Encode: %.2f ms ", + current_fps, avg_frame_time * MS_PER_SECOND, + avg_detect_time * MS_PER_SECOND, avg_encode_time * MS_PER_SECOND); + fflush(stdout); +} + +static void init_processing_state(processing_state &state, const char *type_name, int width, int height) +{ + state.mjpeg_buffer.reserve(width * height * YUV420_BUFFER_RATIO_NUM / YUV420_BUFFER_RATIO_DEN); + state.mjpeg_params = {IMWRITE_JPEG_QUALITY, JPEG_QUALITY, IMWRITE_JPEG_OPTIMIZE, 1, IMWRITE_JPEG_PROGRESSIVE, 0}; + state.pic_size.width = static_cast(width); + state.pic_size.height = static_cast(height); if (strcmp(type_name, "YUYV") == 0) { - // 预分配YUYV缓冲区,每个像素2字节 - yuvFrame.create(height, width, CV_8UC2); + state.yuv_frame.create(height, width, CV_8UC2); } + state.frame_times.reserve(FPS_STAT_WINDOW_SIZE); + state.last_time = high_resolution_clock::now(); +} - // 新增:人脸检测相关变量 - int frame_count = 0; - vector last_detected_faces; - vector last_confidence_scores; - const int DETECT_INTERVAL = 5; /* 5: Detect every 5 frames */ +static int run_processing_loop(VideoCapture &cap, app_config &config, const Ptr &detector) +{ + processing_state state; + camera_params cam_params = {&cap, config.width, config.height, config.fps, config.type_name, &state.retry_count}; + init_processing_state(state, config.type_name, config.width, config.height); + + while (!g_uvcExit) { + auto frame_start = high_resolution_clock::now(); - while (!g_uvc_exit) { if (should_exit_from_stdin()) { - g_uvc_exit = TD_TRUE; + g_uvcExit = TD_TRUE; break; } - cap >> frame; - - if (frame.empty()) { - empty_frame_count++; - printf("Empty frame %d/%d, attempting to reconnect...\n", empty_frame_count, MAX_EMPTY_FRAMES); - - if (empty_frame_count >= MAX_EMPTY_FRAMES) { - if (retry_count < MAX_RETRIES) { - printf("Attempting to reconnect camera (attempt %d/%d)...\n", retry_count + 1, MAX_RETRIES); - cap.release(); - sleep(1); - - cap.open(0, cv::CAP_V4L2); - if (cap.isOpened()) { - cap.set(CAP_PROP_FRAME_WIDTH, width); - cap.set(CAP_PROP_FRAME_HEIGHT, height); - cap.set(CAP_PROP_FPS, fps); - cap.set(CAP_PROP_BUFFERSIZE, 4); /* 4 cap prop buffer size */ - if (strcmp(type_name, "MJPEG") == 0) { - cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); - } else { - cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y', 'U', 'Y', 'V')); - } - - actual_width = cap.get(CAP_PROP_FRAME_WIDTH); - actual_height = cap.get(CAP_PROP_FRAME_HEIGHT); - actual_fps = cap.get(CAP_PROP_FPS); - - printf("Camera reconnected successfully\n"); - printf("New resolution: %dx%d @ %.2f fps\n", actual_width, actual_height, actual_fps); - - retry_count = 0; - empty_frame_count = 0; - device_reconnected = true; - continue; - } - retry_count++; - printf("Retry %d/%d failed\n", retry_count, MAX_RETRIES); - } else { - printf("Failed to reconnect after %d attempts\n", MAX_RETRIES); - g_uvc_exit = TD_TRUE; - break; - } + cap >> state.frame; + + if (state.frame.empty()) { + if (!handle_empty_frame(cam_params, state)) { + continue; } - continue; + break; } - empty_frame_count = 0; - retry_count = 0; + state.empty_frame_count = 0; + state.retry_count = 0; - if (device_reconnected) { - printf("Reinitializing media pipeline...\n"); - if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { - std::cerr << "media reinit failed!" << std::endl; - g_uvc_exit = TD_TRUE; + if (state.device_reconnected) { + config.width = cam_params.width; + config.height = cam_params.height; + init_processing_state(state, config.type_name, config.width, config.height); + if (!reinitialize_media_pipeline(config.type_name, config.width, config.height)) { + g_uvcExit = TD_TRUE; break; } - device_reconnected = false; + state.device_reconnected = false; } - // 人脸检测逻辑 - frame_count++; - bool is_detect_frame = (frame_count % DETECT_INTERVAL == 0); - + double detect_time = 0; + state.frame_count++; + bool is_detect_frame = (state.frame_count % DETECT_INTERVAL_FRAMES == 0); if (is_detect_frame) { - // 预处理阶段 - Mat small_frame; - resize(frame, small_frame, Size(256, 144), 0, 0, INTER_NEAREST); /* 256 144 resize width height */ - - // 检测阶段 - detector->detect(small_frame, faces); - - // 处理检测结果 - const int minFaceSize = 50; /* 50 min face size */ - last_detected_faces.clear(); - last_confidence_scores.clear(); - - if (faces.rows > 0) { - float scale_x = static_cast(frame.cols) / small_frame.cols; - float scale_y = static_cast(frame.rows) / small_frame.rows; - - for (int i = 0; i < faces.rows; ++i) { - int x = static_cast(faces.at(i, 0) * scale_x); - int y = static_cast(faces.at(i, 1) * scale_y); - int w = static_cast(faces.at(i, 2) * scale_x); /* 2 the number of width */ - int h = static_cast(faces.at(i, 3) * scale_y); /* 3 the number of heigth */ - float score = faces.at(i, 4); /* 4 the number of socre */ - - if (w >= minFaceSize && h >= minFaceSize) { - last_detected_faces.emplace_back(x, y, w, h); - last_confidence_scores.push_back(score); - } - } - } + detect_time = detect_faces(state.frame, detector, state.last_detected_faces, state.last_confidence_scores); } - // 绘制人脸框 - for (size_t i = 0; i < last_detected_faces.size(); ++i) { - rectangle(frame, last_detected_faces[i], Scalar(0, 255, 0), 2); /* 0 255 0 R G B, 2 Line width */ - char scoreText[20]; /* 20 text buffer size */ - ret = snprintf(scoreText, sizeof(scoreText), "Conf: %.2f", - last_confidence_scores[i] / 100); /* 100 get the percentage */ - if (ret < 0) { - printf("[func]:%s [line]:%d [info]:snprintf failed\n", __FUNCTION__, __LINE__); - break; - } - putText(frame, scoreText, Point(last_detected_faces[i].x, - last_detected_faces[i].y - 5), /* 5 pic height minus 5 */ - /* 0.5 scaling ratio 0 255 0 R G B, 1 Line width */ - FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1); - } + draw_face_boxes(state.frame, state.last_detected_faces, state.last_confidence_scores); - // 后续处理保持不变 - if (strcmp(type_name, "MJPEG") == 0) { - imencode(".jpg", frame, mjpeg_buffer, mjpeg_params); - ret = sample_uvc_media_send_data(mjpeg_buffer.data(), mjpeg_buffer.size(), - width, &pic_size, "MJPEG"); - } else { - // YUYV格式转换 - cvtColor(frame, yuvFrame, COLOR_BGR2YUV_YUY2); - ret = sample_uvc_media_send_data(yuvFrame.data, yuvFrame.total() * yuvFrame.elemSize(), - yuvFrame.step, &pic_size, "YUYV"); - } + double encode_time = encode_and_send_frame(state.frame, config.type_name, state); - if (ret != 0) { - ret = -errno; - std::cerr << "write error: " << strerror(-ret) << std::endl; - } - } + auto frame_end = high_resolution_clock::now(); + double frame_time = duration(frame_end - frame_start).count(); - printf("--media exit...\n"); + update_performance_stats(frame_time, detect_time, encode_time, state); + } return 0; } + +static bool handle_empty_frame(camera_params &cam_params, processing_state &state) +{ + state.empty_frame_count++; + printf("Empty frame %d/%d, attempting to reconnect...\n", state.empty_frame_count, MAX_EMPTY_FRAMES); + + if (state.empty_frame_count < MAX_EMPTY_FRAMES) { + return false; + } + + if (*cam_params.retry_count >= MAX_RECONNECT_RETRIES) { + printf("Failed to reconnect after %d attempts\n", MAX_RECONNECT_RETRIES); + g_uvcExit = TD_TRUE; + return true; + } + + if (reconnect_camera(cam_params)) { + state.empty_frame_count = 0; + state.device_reconnected = true; + } + return false; +} + +static bool reinitialize_media_pipeline(const char *type_name, int width, int height) +{ + printf("Reinitializing media pipeline...\n"); + sample_uvc_media_stop_receive_data(); + sample_uvc_media_exit(); + if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { + std::cerr << "media reinit failed!" << std::endl; + return false; + } + return true; +} + +static int run_app(int argc, char **argv) +{ + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + printf("IVE硬件加速已禁用(使用CPU模式)\n"); + MemoryManager::optimize_memory(); + register_exit_signal_handlers(); + + uvc_ctrl_info ctrl_info = {0}; + int ret = sample_host_uvc(argc, argv, &ctrl_info); + if (ret != TD_SUCCESS) { + return TD_FAILURE; + } + + VideoCapture cap(CAMERA_DEVICE_INDEX, cv::CAP_V4L2); + if (!cap.isOpened()) { + printf("Error: Failed to open camera device!\n"); + return -1; + } + ScopeGuard cap_guard([&cap] { cap.release(); }); + + int width = ctrl_info.width; + int height = ctrl_info.height; + int fps = DEFAULT_FPS; + const char *type_name = sample_uvc_v4l2_format_name(ctrl_info.pixelformat); + + if (!configure_camera(cap, width, height, fps, type_name)) { + return -1; + } + app_config config = {width, height, fps, type_name}; + Ptr detector = create_face_detector(); + if (!detector) { + printf("Error: Failed to create face detector\n"); + return -1; + } + + if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { + std::cerr << "media start failed!" << std::endl; + return -1; + } + ScopeGuard media_guard([] { + sample_uvc_media_stop_receive_data(); + sample_uvc_media_exit(); + }); + + return run_processing_loop(cap, config, detector); +} + +int main(int argc, char **argv) +{ + return run_app(argc, argv); +} diff --git a/vendor/zsks/demo/opencv_dnn/media_vdec.c b/vendor/zsks/demo/opencv_dnn/media_vdec.c old mode 100755 new mode 100644 index 82957d723c4931c394fc55b2444b60911ef79baf..9ecfb329c0bbffbb0c18fe4438390c478da36d92 --- a/vendor/zsks/demo/opencv_dnn/media_vdec.c +++ b/vendor/zsks/demo/opencv_dnn/media_vdec.c @@ -25,6 +25,48 @@ ot_vb_src g_vdec_vb_source = OT_VB_SRC_MOD; #define REF_NUM 2 #define DISPLAY_NUM 2 +#define VDEC_PIC_ALPHA_MAX 255 +#define VDEC_4K_WIDTH 3840 +#define VDEC_4K_HEIGHT 2160 +#define VDEC_VB_BLK_CNT_FACTOR 10 +#define VDEC_VB_MAX_POOL_CNT 1 +#define VO_DISPLAY_BUF_LEN 3 +#define VDEC_SEND_RETRY_US 1000 +#define VPSS_LOWDELAY_LINE_DIV 4 +#define JPEG_SOI_BYTE0 0xFF +#define JPEG_SOI_BYTE1 0xD8 +#define JPEG_EOI_BYTE1 0xD9 +#define JPEG_MARKER_SKIP_LEN 2 +#define JPEG_SEGMENT_HEADER_LEN 2 +#define JPEG_LEN_FIELD_SHIFT 8 +#define H264_START_CODE_MIN_LEN 8 +#define H265_START_CODE_LEN 6 +#define YUYV_BYTES_PER_PIXEL 2 +#define YUYV_UV_SAMPLE_STEP 2 +#define YUYV_UV_BLOCK_STEP 4 +#define NV12_YUV_SIZE_RATIO_NUM 3 +#define NV12_YUV_SIZE_RATIO_DEN 2 + +typedef struct { + td_char *image_in; + td_char *image_out; + td_u32 width; + td_u32 height; + td_u32 size; + td_u32 stride; +} sample_uvc_yuyv_frame; + +typedef struct { + td_char *image_in; + td_char *image_out; + td_u32 width; + td_u32 height; + td_u32 row_stride; + td_u32 frame_size; + td_u32 cycle_num; + td_s32 pixel_num; +} sample_uvc_yuyv_ctx; + static vdec_display_cfg g_vdec_display_cfg = { .pic_size = PIC_1080P, .intf_sync = OT_VO_OUT_1080P60, @@ -37,30 +79,36 @@ static ot_size g_disp_size; sample_vo_cfg g_vo_config; static td_bool g_is_need_vdec = TD_TRUE; -static td_s32 sample_uvc_init_module_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type, - td_u32 len) +static td_s32 sample_uvc_init_module_vb(sample_vdec_attr *sample_vdec, + td_u32 vdec_chn_num, + ot_payload_type type, td_u32 len) { td_u32 i; td_s32 ret; for (i = 0; (i < vdec_chn_num) && (i < len); i++) { - sample_vdec[i].type = type; - sample_vdec[i].width = g_input_width; - sample_vdec[i].height = g_input_height; - sample_vdec[i].mode = sample_comm_vdec_get_lowdelay_en() ? OT_VDEC_SEND_MODE_COMPAT : - OT_VDEC_SEND_MODE_FRAME; - sample_vdec[i].sample_vdec_video.dec_mode = OT_VIDEO_DEC_MODE_IP; - sample_vdec[i].sample_vdec_video.bit_width = OT_DATA_BIT_WIDTH_8; + sample_vdec[i].type = type; + sample_vdec[i].width = g_input_width; + sample_vdec[i].height = g_input_height; + sample_vdec[i].mode = sample_comm_vdec_get_lowdelay_en() + ? OT_VDEC_SEND_MODE_COMPAT + : OT_VDEC_SEND_MODE_FRAME; + sample_vdec[i].sample_vdec_video.dec_mode = OT_VIDEO_DEC_MODE_IP; + sample_vdec[i].sample_vdec_video.bit_width = OT_DATA_BIT_WIDTH_8; if (type == OT_PT_JPEG) { sample_vdec[i].sample_vdec_video.ref_frame_num = 0; } else { sample_vdec[i].sample_vdec_video.ref_frame_num = REF_NUM; } - sample_vdec[i].display_frame_num = DISPLAY_NUM; - sample_vdec[i].frame_buf_cnt = (type == OT_PT_JPEG) ? (sample_vdec[i].display_frame_num + 1) : - (sample_vdec[i].sample_vdec_video.ref_frame_num + sample_vdec[i].display_frame_num + 1); + sample_vdec[i].display_frame_num = DISPLAY_NUM; + sample_vdec[i].frame_buf_cnt = + (type == OT_PT_JPEG) + ? (sample_vdec[i].display_frame_num + 1) + : (sample_vdec[i].sample_vdec_video.ref_frame_num + + sample_vdec[i].display_frame_num + 1); if (type == OT_PT_JPEG) { - sample_vdec[i].sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - sample_vdec[i].sample_vdec_picture.alpha = 255; /* 255:pic alpha value */ + sample_vdec[i].sample_vdec_picture.pixel_format = + OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + sample_vdec[i].sample_vdec_picture.alpha = VDEC_PIC_ALPHA_MAX; } } ret = sample_comm_vdec_init_vb_pool(vdec_chn_num, &sample_vdec[0], len); @@ -71,13 +119,15 @@ static td_s32 sample_uvc_init_module_vb(sample_vdec_attr *sample_vdec, td_u32 vd return ret; } -static td_s32 sample_uvc_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type, - td_u32 len) +static td_s32 sample_uvc_init_sys_and_vb(sample_vdec_attr *sample_vdec, + td_u32 vdec_chn_num, + ot_payload_type type, td_u32 len) { ot_vb_cfg vb_cfg; ot_pic_buf_attr buf_attr = {0}; td_s32 ret; - ret = sample_comm_sys_get_pic_size(g_vdec_display_cfg.pic_size, &g_disp_size); + ret = + sample_comm_sys_get_pic_size(g_vdec_display_cfg.pic_size, &g_disp_size); if (ret != TD_SUCCESS) { sample_print("sys get pic size fail for %#x!\n", ret); return ret; @@ -85,13 +135,13 @@ static td_s32 sample_uvc_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 v buf_attr.align = 0; buf_attr.bit_width = OT_DATA_BIT_WIDTH_8; buf_attr.compress_mode = OT_COMPRESS_MODE_SEG; - buf_attr.height = 2160; /* 2160:height */ - buf_attr.width = 3840; /* 3840:width */ + buf_attr.height = VDEC_4K_HEIGHT; + buf_attr.width = VDEC_4K_WIDTH; buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - (td_void)memset_s(&vb_cfg, sizeof(ot_vb_cfg), 0, sizeof(ot_vb_cfg)); - vb_cfg.max_pool_cnt = 1; - vb_cfg.common_pool[0].blk_cnt = 10 * vdec_chn_num; /* 10:common vb cnt */ + (td_void) memset_s(&vb_cfg, sizeof(ot_vb_cfg), 0, sizeof(ot_vb_cfg)); + vb_cfg.max_pool_cnt = VDEC_VB_MAX_POOL_CNT; + vb_cfg.common_pool[0].blk_cnt = VDEC_VB_BLK_CNT_FACTOR * vdec_chn_num; vb_cfg.common_pool[0].blk_size = ot_common_get_pic_buf_size(&buf_attr); ret = sample_comm_sys_init(&vb_cfg); if (ret != TD_SUCCESS) { @@ -101,7 +151,8 @@ static td_s32 sample_uvc_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 v } if (g_is_need_vdec == TD_TRUE) { - ret = sample_uvc_init_module_vb(&sample_vdec[0], vdec_chn_num, type, len); + ret = + sample_uvc_init_module_vb(&sample_vdec[0], vdec_chn_num, type, len); if (ret != TD_SUCCESS) { sample_print("init mod vb fail for %#x!\n", ret); sample_comm_vdec_exit_vb_pool(); @@ -127,7 +178,9 @@ static td_s32 sample_uvc_vdec_bind_vpss(td_u32 vpss_grp_num) return ret; } -static td_void sample_uvc_stop_vpss(ot_vpss_grp vpss_grp, td_bool *vpss_chn_enable, td_u32 chn_array_size) +static td_void sample_uvc_stop_vpss(ot_vpss_grp vpss_grp, + td_bool *vpss_chn_enable, + td_u32 chn_array_size) { td_s32 i; for (i = vpss_grp; i >= 0; i--) { @@ -155,12 +208,12 @@ static td_void sample_uvc_config_vpss_grp_attr(ot_vpss_grp_attr *vpss_grp_attr) vpss_grp_attr->max_height = g_input_height; vpss_grp_attr->frame_rate.src_frame_rate = -1; vpss_grp_attr->frame_rate.dst_frame_rate = -1; - vpss_grp_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - vpss_grp_attr->nr_en = TD_FALSE; - vpss_grp_attr->ie_en = TD_FALSE; - vpss_grp_attr->dci_en = TD_FALSE; + vpss_grp_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vpss_grp_attr->nr_en = TD_FALSE; + vpss_grp_attr->ie_en = TD_FALSE; + vpss_grp_attr->dci_en = TD_FALSE; vpss_grp_attr->dei_mode = OT_VPSS_DEI_MODE_OFF; - vpss_grp_attr->buf_share_en = TD_FALSE; + vpss_grp_attr->buf_share_en = TD_FALSE; } static td_void sample_uvc_stop_vdec(td_u32 vdec_chn_num) @@ -174,7 +227,8 @@ static td_void sample_uvc_stop_vdec(td_u32 vdec_chn_num) return; } -static td_s32 sample_uvc_start_vdec(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, td_u32 len) +static td_s32 sample_uvc_start_vdec(sample_vdec_attr *sample_vdec, + td_u32 vdec_chn_num, td_u32 len) { td_s32 ret; @@ -203,7 +257,8 @@ static td_s32 sample_uvc_config_vpss_ldy_attr(td_u32 vpss_grp_num) return ret; } vpss_ldy_info.enable = TD_TRUE; - vpss_ldy_info.line_cnt = g_disp_size.height / 4 * 1; /* 1/4:lowdelay line num */ + vpss_ldy_info.line_cnt = + g_disp_size.height / VPSS_LOWDELAY_LINE_DIV * 1; ret = ss_mpi_vpss_set_low_delay_attr(i, 0, &vpss_ldy_info); if (ret != TD_SUCCESS) { sample_print("vpss set low delay attr fail for %#x!\n", ret); @@ -214,55 +269,61 @@ static td_s32 sample_uvc_config_vpss_ldy_attr(td_u32 vpss_grp_num) } static td_s32 sample_uvc_start_vpss(ot_vpss_grp *vpss_grp, td_u32 vpss_grp_num, - td_bool *vpss_chn_enable, td_u32 arr_len) + td_bool *vpss_chn_enable, td_u32 arr_len) { td_u32 i; td_s32 ret; ot_vpss_chn_attr vpss_chn_attr[OT_VPSS_MAX_CHN_NUM]; ot_vpss_grp_attr vpss_grp_attr = {0}; sample_uvc_config_vpss_grp_attr(&vpss_grp_attr); - (td_void)memset_s(vpss_chn_enable, arr_len * sizeof(td_bool), 0, arr_len * sizeof(td_bool)); + (td_void) memset_s(vpss_chn_enable, arr_len * sizeof(td_bool), 0, + arr_len * sizeof(td_bool)); if (arr_len > 1) { vpss_chn_enable[0] = TD_TRUE; - vpss_chn_attr[0].width = g_disp_size.width; - vpss_chn_attr[0].height = g_disp_size.height; - vpss_chn_attr[0].chn_mode = OT_VPSS_CHN_MODE_USER; - vpss_chn_attr[0].compress_mode = OT_COMPRESS_MODE_NONE; - vpss_chn_attr[0].pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - vpss_chn_attr[0].video_format = OT_VIDEO_FORMAT_LINEAR; + vpss_chn_attr[0].width = g_disp_size.width; + vpss_chn_attr[0].height = g_disp_size.height; + vpss_chn_attr[0].chn_mode = OT_VPSS_CHN_MODE_USER; + vpss_chn_attr[0].compress_mode = OT_COMPRESS_MODE_NONE; + vpss_chn_attr[0].pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vpss_chn_attr[0].video_format = OT_VIDEO_FORMAT_LINEAR; vpss_chn_attr[0].frame_rate.src_frame_rate = -1; vpss_chn_attr[0].frame_rate.dst_frame_rate = -1; - vpss_chn_attr[0].depth = 0; - vpss_chn_attr[0].mirror_en = TD_FALSE; - vpss_chn_attr[0].flip_en = TD_FALSE; - vpss_chn_attr[0].border_en = TD_FALSE; - vpss_chn_attr[0].aspect_ratio.mode = OT_ASPECT_RATIO_NONE; + vpss_chn_attr[0].depth = 0; + vpss_chn_attr[0].mirror_en = TD_FALSE; + vpss_chn_attr[0].flip_en = TD_FALSE; + vpss_chn_attr[0].border_en = TD_FALSE; + vpss_chn_attr[0].aspect_ratio.mode = OT_ASPECT_RATIO_NONE; } for (i = 0; i < vpss_grp_num; i++) { *vpss_grp = i; ret = sample_common_vpss_start(*vpss_grp, &vpss_chn_enable[0], - &vpss_grp_attr, vpss_chn_attr, OT_VPSS_MAX_CHN_NUM); + &vpss_grp_attr, vpss_chn_attr, + OT_VPSS_MAX_CHN_NUM); if (ret != TD_SUCCESS) { sample_print("start VPSS fail for %#x!\n", ret); - sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], + OT_VPSS_MAX_CHN_NUM); return ret; } } ret = sample_uvc_config_vpss_ldy_attr(vpss_grp_num); if (ret != TD_SUCCESS) { - sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], + OT_VPSS_MAX_CHN_NUM); return ret; } ret = sample_uvc_vdec_bind_vpss(vpss_grp_num); if (ret != TD_SUCCESS) { sample_uvc_vdec_unbind_vpss(vpss_grp_num); - sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], + OT_VPSS_MAX_CHN_NUM); } return ret; } -static td_s32 sample_uvc_vpss_bind_vo(sample_vo_cfg vo_config, td_u32 vpss_grp_num) +static td_s32 sample_uvc_vpss_bind_vo(sample_vo_cfg vo_config, + td_u32 vpss_grp_num) { td_u32 i; ot_vo_layer vo_layer; @@ -278,7 +339,8 @@ static td_s32 sample_uvc_vpss_bind_vo(sample_vo_cfg vo_config, td_u32 vpss_grp_n return ret; } -static td_s32 sample_uvc_vpss_unbind_vo(td_u32 vpss_grp_num, sample_vo_cfg vo_config) +static td_s32 sample_uvc_vpss_unbind_vo(td_u32 vpss_grp_num, + sample_vo_cfg vo_config) { td_u32 i; ot_vo_layer vo_layer = vo_config.vo_dev; @@ -294,23 +356,23 @@ static td_s32 sample_uvc_vpss_unbind_vo(td_u32 vpss_grp_num, sample_vo_cfg vo_co static td_void sample_uvc_get_default_vo_cfg(sample_vo_cfg *vo_config) { - vo_config->vo_dev = SAMPLE_VO_DEV_UHD; - vo_config->vo_intf_type = g_vdec_display_cfg.intf_type; - vo_config->intf_sync = g_vdec_display_cfg.intf_sync; - vo_config->pic_size = g_vdec_display_cfg.pic_size; - vo_config->bg_color = COLOR_RGB_BLUE; - vo_config->dis_buf_len = 3; /* 3:buf length */ + vo_config->vo_dev = SAMPLE_VO_DEV_UHD; + vo_config->vo_intf_type = g_vdec_display_cfg.intf_type; + vo_config->intf_sync = g_vdec_display_cfg.intf_sync; + vo_config->pic_size = g_vdec_display_cfg.pic_size; + vo_config->bg_color = COLOR_RGB_BLUE; + vo_config->dis_buf_len = VO_DISPLAY_BUF_LEN; vo_config->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8; - vo_config->vo_mode = VO_MODE_1MUX; - vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - vo_config->disp_rect.x = 0; - vo_config->disp_rect.y = 0; - vo_config->disp_rect.width = g_disp_size.width; - vo_config->disp_rect.height = g_disp_size.height; - vo_config->image_size.width = g_disp_size.width; + vo_config->vo_mode = VO_MODE_1MUX; + vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vo_config->disp_rect.x = 0; + vo_config->disp_rect.y = 0; + vo_config->disp_rect.width = g_disp_size.width; + vo_config->disp_rect.height = g_disp_size.height; + vo_config->image_size.width = g_disp_size.width; vo_config->image_size.height = g_disp_size.height; - vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE; - vo_config->compress_mode = OT_COMPRESS_MODE_NONE; + vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE; + vo_config->compress_mode = OT_COMPRESS_MODE_NONE; } static td_s32 sample_uvc_start_vo(sample_vo_cfg *vo_config, td_u32 vpss_grp_num) @@ -348,8 +410,7 @@ static ot_payload_type sample_uvc_get_payload_type(const td_char *type_name) static td_void sample_uvc_update_vdec_flag(const td_char *type_name) { - if ((strcmp(type_name, "H264") == 0) || - (strcmp(type_name, "H265") == 0) || + if ((strcmp(type_name, "H264") == 0) || (strcmp(type_name, "H265") == 0) || (strcmp(type_name, "MJPEG") == 0)) { g_is_need_vdec = TD_TRUE; } else { @@ -357,7 +418,8 @@ static td_void sample_uvc_update_vdec_flag(const td_char *type_name) } } -td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, td_u32 height) +td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, + td_u32 height) { td_s32 ret; td_u32 vdec_chn_num; @@ -379,15 +441,18 @@ td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, td_u32 heig return TD_FAILURE; } } - ret = sample_uvc_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, payload_type, OT_VDEC_MAX_CHN_NUM); + ret = sample_uvc_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, + payload_type, OT_VDEC_MAX_CHN_NUM); if (ret != TD_SUCCESS) { return ret; } - ret = sample_uvc_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM); + ret = sample_uvc_start_vdec(&sample_vdec[0], vdec_chn_num, + OT_VDEC_MAX_CHN_NUM); if (ret != TD_SUCCESS) { goto stop_sys; } - ret = sample_uvc_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + ret = sample_uvc_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], + OT_VPSS_MAX_CHN_NUM); if (ret != TD_SUCCESS) { goto stop_vdec; } @@ -417,9 +482,9 @@ td_s32 sample_uvc_media_exit(td_void) td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM] = {0}; vpss_chn_enable[0] = TD_TRUE; - (td_void)sample_uvc_vpss_unbind_vo(vpss_grp_num, g_vo_config); + (td_void) sample_uvc_vpss_unbind_vo(vpss_grp_num, g_vo_config); sample_comm_vo_stop_vo(&g_vo_config); - (td_void)sample_uvc_vdec_unbind_vpss(vpss_grp_num); + (td_void) sample_uvc_vdec_unbind_vpss(vpss_grp_num); sample_uvc_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); sample_uvc_stop_vdec(vdec_chn_num); sample_comm_sys_exit(); @@ -427,8 +492,9 @@ td_s32 sample_uvc_media_exit(td_void) return TD_SUCCESS; } -static td_void sample_uvc_cut_stream_for_mjpeg(td_void *data, td_u32 size, td_s32 chn_id, - td_s32 *read_num, td_u32 *start) +static td_void sample_uvc_cut_stream_for_mjpeg(td_void *data, td_u32 size, + td_s32 chn_id, td_s32 *read_num, + td_u32 *start) { td_s32 i; td_u32 len; @@ -436,18 +502,18 @@ static td_void sample_uvc_cut_stream_for_mjpeg(td_void *data, td_u32 size, td_s3 td_u8 *buf = data; td_bool find_start = TD_FALSE; for (i = 0; i < read_len - 1; i++) { - if (buf[i] == 0xFF && buf[i + 1] == 0xD8) { /* 0xFFD8: JPEG起始标记 */ + if (buf[i] == JPEG_SOI_BYTE0 && buf[i + 1] == JPEG_SOI_BYTE1) { *start = i; find_start = TD_TRUE; - i = i + 2; /* 2: 跳过标记长度 */ + i = i + JPEG_MARKER_SKIP_LEN; break; } } - /* 3: 检查下一个标记头所需长度 */ - for (; i < read_len - 3; i++) { - if ((buf[i] == 0xFF) && (buf[i + 1] & 0xF0) == 0xE0) { - len = (buf[i + 2] << 8) + buf[i + 3]; /* 2 3 index 8: 长度字段占2字节 */ + for (; i < read_len - JPEG_SEGMENT_HEADER_LEN; i++) { + if ((buf[i] == JPEG_SOI_BYTE0) && (buf[i + 1] & 0xF0) == 0xE0) { + len = (buf[i + JPEG_MARKER_SKIP_LEN] << JPEG_LEN_FIELD_SHIFT) + + buf[i + JPEG_SEGMENT_HEADER_LEN]; i += 1 + len; } else { break; @@ -455,44 +521,47 @@ static td_void sample_uvc_cut_stream_for_mjpeg(td_void *data, td_u32 size, td_s3 } for (; i < read_len - 1; i++) { - if (buf[i] == 0xFF && buf[i + 1] == 0xD9) { /* 0xFFD9: JPEG结束标记 */ + if (buf[i] == JPEG_SOI_BYTE0 && buf[i + 1] == JPEG_EOI_BYTE1) { break; } } - read_len = i + 2; /* 2: 包含结束标记 */ + read_len = i + JPEG_MARKER_SKIP_LEN; if (find_start == TD_FALSE) { - sample_print("chn %d can not find JPEG start code! read_len %d!\n", chn_id, read_len); + sample_print("chn %d can not find JPEG start code! read_len %d!\n", + chn_id, read_len); } *read_num = read_len; } -static td_void sample_uvc_cut_stream_for_h264(td_void *data, td_u32 size, td_s32 chn_id, td_s32 *read_num) +static td_void sample_uvc_cut_stream_for_h264(td_void *data, td_u32 size, + td_s32 chn_id, td_s32 *read_num) { td_bool find_start = TD_FALSE; td_bool find_end = TD_FALSE; td_s32 i; td_u8 *buf = data; td_s32 read_len = size; - for (i = 0; i < read_len - 8; i++) { /* 8: 起始码最小长度 */ + for (i = 0; i < read_len - H264_START_CODE_MIN_LEN; i++) { int tmp = buf[i + 3] & 0x1F; /* 0x1F: NALU类型掩码 */ /* 0x5: IDR帧, 0x1: 非IDR帧 0x80: 关键帧标志 2 index */ if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && - (((tmp == 0x5 || tmp == 0x1) && ((buf[i + 4] & 0x80) == 0x80)) || /* 4 index */ - (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ + (((tmp == 0x5 || tmp == 0x1) && + ((buf[i + 4] & 0x80) == 0x80)) || /* 4 index */ + (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ find_start = TD_TRUE; - i += 8; /* 8: 跳过起始码 */ + i += H264_START_CODE_MIN_LEN; break; } } - for (; i < read_len - 8; i++) { /* 8: 查找结束所需最小长度 */ + for (; i < read_len - H264_START_CODE_MIN_LEN; i++) { int tmp = buf[i + 3] & 0x1F; /* 0x1F: NALU类型掩码 */ - if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 2 index */ - (tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 || /* 15 SEI 7 SPS 8 PPS 6 SEI */ - ((tmp == 5 || tmp == 1) && ((buf[i + 4] & 0x80) == 0x80)) || /* 5 1 帧起始类型 4 index */ - (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 2 index */ + (tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 || /* 15 SEI 7 SPS 8 PPS 6 SEI */ + ((tmp == 5 || tmp == 1) && ((buf[i + 4] & 0x80) == 0x80)) || /* 5 1 帧起始类型 4 index */ + (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ find_end = TD_TRUE; break; } @@ -503,17 +572,19 @@ static td_void sample_uvc_cut_stream_for_h264(td_void *data, td_u32 size, td_s32 } if (find_start == TD_FALSE) { - sample_print("chn %d can not find H264 start code! read_len %d!\n", chn_id, read_len); + sample_print("chn %d can not find H264 start code! read_len %d!\n", + chn_id, read_len); } if (find_end == TD_FALSE) { - read_len = i + 8; /* 8: 包含下一帧起始码 */ + read_len = i + H264_START_CODE_MIN_LEN; } *read_num = read_len; } -static td_void sample_uvc_cut_stream_for_h265(td_void *data, td_u32 size, td_s32 chn_id, td_s32 *read_num) +static td_void sample_uvc_cut_stream_for_h265(td_void *data, td_u32 size, + td_s32 chn_id, td_s32 *read_num) { td_bool find_start = TD_FALSE; td_bool find_end = TD_FALSE; @@ -521,23 +592,28 @@ static td_void sample_uvc_cut_stream_for_h265(td_void *data, td_u32 size, td_s32 td_s32 i; td_u8 *buf = data; td_s32 read_len = size; - for (i = 0; i < read_len - 6; i++) { /* 6:h265 frame start code length */ - td_u32 tmp = (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ - new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 1 2:index */ - (tmp <= 21) && ((buf[i + 5] & 0x80) == 0x80)); /* 5:index 21 0x80:frame start marker */ + for (i = 0; i < read_len - H265_START_CODE_LEN; i++) { + td_u32 tmp = + (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ + new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && + buf[i + 2] == 1 && /* 1 2:index */ + (tmp <= 21) && ((buf[i + 5] & 0x80) == 0x80)); /* 5:index 21 0x80:frame start marker */ if (new_pic) { find_start = TD_TRUE; - i += 6; /* 6:h265 frame start code length */ + i += H265_START_CODE_LEN; break; } } - for (; i < read_len - 6; i++) { /* 6:h265 frame start code length */ - td_u32 tmp = (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ - new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 1 2:index */ - (tmp == 32 || tmp == 33 || tmp == 34 || tmp == 39 || tmp == 40 || /* 32 33 34 39 40:frame start marker */ - ((tmp <= 21) && (buf[i + 5] & 0x80) == 0x80))); /* 5:index 21 0x80:frame start marker */ + for (; i < read_len - H265_START_CODE_LEN; i++) { + td_u32 tmp = + (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ + new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && + buf[i + 2] == 1 && /* 1 2:index */ + (tmp == 32 || tmp == 33 || tmp == 34 || /* 32 33 34:frame start marker */ + tmp == 39 || tmp == 40 || /* 39 40:frame start marker */ + ((tmp <= 21) && (buf[i + 5] & 0x80) == 0x80))); /* 5:index 21 0x80:frame start marker */ if (new_pic) { find_end = TD_TRUE; @@ -550,27 +626,31 @@ static td_void sample_uvc_cut_stream_for_h265(td_void *data, td_u32 size, td_s32 } if (find_start == TD_FALSE) { - sample_print("chn %d can not find H265 start code! read_len %d!\n", chn_id, read_len); + sample_print("chn %d can not find H265 start code! read_len %d!\n", + chn_id, read_len); } if (find_end == TD_FALSE) { - read_len = i + 6; /* 6:h265 frame start code length */ + read_len = i + H265_START_CODE_LEN; } *read_num = read_len; } -static td_s32 sample_uvc_prepare_frame_info(ot_vb_blk vb_blk, const ot_pic_buf_attr *buf_attr, - const ot_vb_calc_cfg *calc_cfg, ot_video_frame_info *video_frame) +static td_s32 sample_uvc_prepare_frame_info(ot_vb_blk vb_blk, + const ot_pic_buf_attr *buf_attr, + const ot_vb_calc_cfg *calc_cfg, + ot_video_frame_info *video_frame) { - video_frame->video_frame.header_phys_addr[0] = ss_mpi_vb_handle_to_phys_addr(vb_blk); + video_frame->video_frame.header_phys_addr[0] = + ss_mpi_vb_handle_to_phys_addr(vb_blk); if (video_frame->video_frame.header_phys_addr[0] == TD_NULL) { sample_print("ss_mpi_vb_handle_to_phys_addr fail\n"); return TD_FAILURE; } - video_frame->video_frame.header_virt_addr[0] = - (td_u8*)ss_mpi_sys_mmap(video_frame->video_frame.header_phys_addr[0], calc_cfg->vb_size); + video_frame->video_frame.header_virt_addr[0] = (td_u8 *)ss_mpi_sys_mmap( + video_frame->video_frame.header_phys_addr[0], calc_cfg->vb_size); if (video_frame->video_frame.header_virt_addr[0] == TD_NULL) { sample_print("ss_mpi_sys_mmap fail\n"); return TD_FAILURE; @@ -607,7 +687,8 @@ static td_s32 sample_uvc_prepare_frame_info(ot_vb_blk vb_blk, const ot_pic_buf_a return TD_SUCCESS; } -static td_void sample_uvc_buf_attr_init(const ot_size *pic_size, ot_pic_buf_attr *buf_attr) +static td_void sample_uvc_buf_attr_init(const ot_size *pic_size, + ot_pic_buf_attr *buf_attr) { buf_attr->width = pic_size->width; buf_attr->height = pic_size->height; @@ -617,50 +698,82 @@ static td_void sample_uvc_buf_attr_init(const ot_size *pic_size, ot_pic_buf_attr buf_attr->bit_width = OT_DATA_BIT_WIDTH_8; } -static td_void sample_uvc_yuyv_to_nv12(td_char *image_in, td_u32 width, td_u32 height, - td_u32 size, td_char *image_out) +static td_void sample_uvc_yuyv_ctx_init(sample_uvc_yuyv_ctx *ctx, + const sample_uvc_yuyv_frame *frame) { - td_s32 pixel_num = width * height; - td_u32 cycle_num = size / pixel_num / 2; /* 2: YUYV格式中每个像素占2字节 */ - - td_char *y = image_out; - td_char *uv = image_out + pixel_num; - - td_char *start = image_in; - td_u32 i = 0; - td_u32 j = 0; - td_u32 k = 0; + ctx->image_in = frame->image_in; + ctx->image_out = frame->image_out; + ctx->width = frame->width; + ctx->height = frame->height; + ctx->pixel_num = (td_s32)(frame->width * frame->height); + ctx->row_stride = (frame->stride != 0) ? frame->stride : + frame->width * YUYV_BYTES_PER_PIXEL; + ctx->frame_size = ctx->row_stride * frame->height; + ctx->cycle_num = (ctx->frame_size != 0) ? frame->size / ctx->frame_size : 0; +} - /* Y */ - for (i = 0; i < cycle_num; i++) { - int index = 0; - for (j = 0; j < pixel_num * 2; j = j + 2) { /* 2: 跳过UV分量,每次取Y */ - *(y + index) = *(start + j); - index++; +static td_void sample_uvc_yuyv_copy_y_plane(const sample_uvc_yuyv_ctx *ctx) +{ + td_char *y = ctx->image_out; + td_u32 nv12_frame_size = + (td_u32)ctx->pixel_num * NV12_YUV_SIZE_RATIO_NUM / NV12_YUV_SIZE_RATIO_DEN; + td_u32 i; + td_u32 row; + td_u32 col; + + for (i = 0; i < ctx->cycle_num; i++) { + td_char *frame_start = ctx->image_in + ctx->frame_size * i; + td_s32 y_index = 0; + + for (row = 0; row < ctx->height; row++) { + td_char *row_start = frame_start + row * ctx->row_stride; + for (col = 0; col < ctx->width * YUYV_BYTES_PER_PIXEL; + col += YUYV_BYTES_PER_PIXEL) { + y[y_index++] = row_start[col]; + } } - start = image_in + pixel_num * 2 * i; /* 2: 每帧YUYV数据跨度 */ - y = y + pixel_num * 3 / 2; /* 3/2: NV12中Y+UV的总大小比例 */ - } - - /* UV */ - start = image_in; - for (i = 0; i < cycle_num; i++) { - int uv_index = 0; - for (j = 0; j < height; j = j + 2) { /* 2: 隔行采样UV */ - /* 2: YUYV宽度步进 4: 每两个像素的YUYV数据块 1: 取U分量的位置偏移 2: 取下一个V分量的偏移 */ - for (k = j * width * 2 + 1; k < width * 2 * (j + 1); k = k + 4) { - *(uv + uv_index) = *(start + k); /* U分量 */ - *(uv + uv_index + 1) = *(start + k + 2); /* 2 取下一个V分量的偏移 */ - uv_index += 2; /* 2: UV平面存储步进 */ + y += nv12_frame_size; + } +} + +static td_void sample_uvc_yuyv_copy_uv_plane(const sample_uvc_yuyv_ctx *ctx) +{ + td_char *uv = ctx->image_out + ctx->pixel_num; + td_u32 nv12_frame_size = + (td_u32)ctx->pixel_num * NV12_YUV_SIZE_RATIO_NUM / NV12_YUV_SIZE_RATIO_DEN; + td_u32 i; + td_u32 row; + td_u32 col; + + for (i = 0; i < ctx->cycle_num; i++) { + td_char *frame_start = ctx->image_in + ctx->frame_size * i; + td_s32 uv_index = 0; + + for (row = 0; row < ctx->height; row += YUYV_UV_SAMPLE_STEP) { + td_char *row_start = frame_start + row * ctx->row_stride; + for (col = 1; col < ctx->width * YUYV_BYTES_PER_PIXEL; + col += YUYV_UV_BLOCK_STEP) { + uv[uv_index] = row_start[col]; + uv[uv_index + 1] = row_start[col + YUYV_UV_SAMPLE_STEP]; + uv_index += YUYV_UV_SAMPLE_STEP; } } - start = image_in + pixel_num * 2 * i; /* 2: 每帧YUYV数据跨度 */ - uv = uv + pixel_num * 3 / 2; /* 3/2: NV12中Y+UV的总大小比例 */ + uv += nv12_frame_size; } } -static td_void sample_uvc_update_vb_cfg(ot_pixel_format pixel_format, td_u32 stride, const ot_size *pic_size, - ot_vb_calc_cfg *calc_cfg) +static td_void sample_uvc_yuyv_to_nv12(const sample_uvc_yuyv_frame *frame) +{ + sample_uvc_yuyv_ctx ctx; + + sample_uvc_yuyv_ctx_init(&ctx, frame); + sample_uvc_yuyv_copy_y_plane(&ctx); + sample_uvc_yuyv_copy_uv_plane(&ctx); +} + +static td_void sample_uvc_update_vb_cfg(ot_pixel_format pixel_format, + td_u32 stride, const ot_size *pic_size, + ot_vb_calc_cfg *calc_cfg) { if (pixel_format != OT_PIXEL_FORMAT_YUYV_PACKAGE_422) { return; @@ -670,8 +783,10 @@ static td_void sample_uvc_update_vb_cfg(ot_pixel_format pixel_format, td_u32 str calc_cfg->main_y_size = calc_cfg->main_stride * pic_size->height; } -static td_s32 sample_uvc_send_frame_to_vpss(td_void *data, td_u32 size, td_u32 stride, - const ot_size *pic_size, ot_pixel_format pixel_format) +static td_s32 sample_uvc_send_frame_to_vpss(td_void *data, td_u32 size, + td_u32 stride, + const ot_size *pic_size, + ot_pixel_format pixel_format) { td_s32 ret; ot_vpss_grp grp = 0; @@ -683,21 +798,32 @@ static td_s32 sample_uvc_send_frame_to_vpss(td_void *data, td_u32 size, td_u32 s sample_uvc_buf_attr_init(pic_size, &buf_attr); ot_common_get_pic_buf_cfg(&buf_attr, &calc_cfg); sample_uvc_update_vb_cfg(pixel_format, stride, pic_size, &calc_cfg); - vb_blk = ss_mpi_vb_get_blk(OT_VB_INVALID_POOL_ID, calc_cfg.vb_size, TD_NULL); + vb_blk = + ss_mpi_vb_get_blk(OT_VB_INVALID_POOL_ID, calc_cfg.vb_size, TD_NULL); if (vb_blk == OT_VB_INVALID_HANDLE) { sample_print("get vb blk(size:%d) failed!\n", calc_cfg.vb_size); return TD_FAILURE; } - ret = sample_uvc_prepare_frame_info(vb_blk, &buf_attr, &calc_cfg, &frame_info); + ret = sample_uvc_prepare_frame_info(vb_blk, &buf_attr, &calc_cfg, + &frame_info); if (ret != TD_SUCCESS) { return ret; } if (pixel_format == OT_PIXEL_FORMAT_YUYV_PACKAGE_422) { - sample_uvc_yuyv_to_nv12(data, pic_size->width, pic_size->height, size, frame_info.video_frame.virt_addr[0]); + sample_uvc_yuyv_frame yuyv_frame = { + .image_in = data, + .image_out = frame_info.video_frame.virt_addr[0], + .width = pic_size->width, + .height = pic_size->height, + .size = size, + .stride = stride, + }; + sample_uvc_yuyv_to_nv12(&yuyv_frame); } else { frame_info.video_frame.pixel_format = pixel_format; - (td_void)memcpy_s(frame_info.video_frame.virt_addr[0], size, data, size); + (td_void) + memcpy_s(frame_info.video_frame.virt_addr[0], size, data, size); } ret = ss_mpi_vpss_send_frame(grp, &frame_info, milli_sec); if (ret != TD_SUCCESS) { @@ -713,7 +839,8 @@ static td_s32 sample_uvc_send_frame_to_vpss(td_void *data, td_u32 size, td_u32 s return ret; } -static td_s32 sample_uvc_get_pixel_format(const td_char *type_name, ot_pixel_format *pixel_format) +static td_s32 sample_uvc_get_pixel_format(const td_char *type_name, + ot_pixel_format *pixel_format) { if (strcmp(type_name, "YUYV") == 0) { *pixel_format = OT_PIXEL_FORMAT_YUYV_PACKAGE_422; @@ -730,7 +857,8 @@ static td_s32 sample_uvc_get_pixel_format(const td_char *type_name, ot_pixel_for } td_s32 sample_uvc_media_send_data(td_void *data, td_u32 size, td_u32 stride, - const ot_size *pic_size, const td_char *type_name) + const ot_size *pic_size, + const td_char *type_name) { td_bool end_of_stream = TD_FALSE; td_s32 read_len = size; @@ -753,20 +881,21 @@ td_s32 sample_uvc_media_send_data(td_void *data, td_u32 size, td_u32 stride, if (ret != TD_SUCCESS) { return ret; } - return sample_uvc_send_frame_to_vpss(data, size, stride, pic_size, pixel_format); + return sample_uvc_send_frame_to_vpss(data, size, stride, pic_size, + pixel_format); } - vdec_stream.addr = buf + start; - vdec_stream.len = read_len; - vdec_stream.end_of_frame = TD_TRUE; + vdec_stream.addr = buf + start; + vdec_stream.len = read_len; + vdec_stream.end_of_frame = TD_TRUE; vdec_stream.end_of_stream = end_of_stream; - vdec_stream.need_display = 1; + vdec_stream.need_display = 1; while (send_again == TD_TRUE) { ss_mpi_sys_get_cur_pts(&vdec_stream.pts); ret = ss_mpi_vdec_send_stream(chn_id, &vdec_stream, 0); if (ret != TD_SUCCESS) { - usleep(1000); /* 1000 sleep 1000us */ + usleep(VDEC_SEND_RETRY_US); sample_print("send stream to vdec failed!\n"); continue; } else { @@ -774,7 +903,7 @@ td_s32 sample_uvc_media_send_data(td_void *data, td_u32 size, td_u32 stride, } send_again = TD_FALSE; } - usleep(1000); /* 1000 sleep 1000us */ + usleep(VDEC_SEND_RETRY_US); return TD_SUCCESS; } diff --git a/vendor/zsks/demo/opencv_dnn/media_vdec.h b/vendor/zsks/demo/opencv_dnn/media_vdec.h old mode 100755 new mode 100644 index dcd6942734b98e09e5befc75a6cac348d7fa38c8..c228db57556d19798a753b499e341e03dbbe4eff --- a/vendor/zsks/demo/opencv_dnn/media_vdec.h +++ b/vendor/zsks/demo/opencv_dnn/media_vdec.h @@ -25,10 +25,10 @@ extern "C" { #endif #endif -td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, td_u32 height); +td_s32 sample_uvc_media_init(const td_char* type_name, td_u32 width, td_u32 height); td_s32 sample_uvc_media_exit(td_void); -td_s32 sample_uvc_media_send_data(td_void *data, td_u32 data_size, td_u32 stride, - const ot_size *pic_size, const td_char *type_name); +td_s32 sample_uvc_media_send_data( + td_void* data, td_u32 data_size, td_u32 stride, const ot_size* pic_size, const td_char* type_name); td_s32 sample_uvc_media_stop_receive_data(td_void); #ifdef __cplusplus @@ -37,5 +37,4 @@ td_s32 sample_uvc_media_stop_receive_data(td_void); #endif #endif /* End of #ifdef __cplusplus */ - #endif /* end of #ifndef __MEDIA_VDEC_H__ */ diff --git a/vendor/zsks/demo/opencv_dnn/pic/desktop.ini b/vendor/zsks/demo/opencv_dnn/pic/desktop.ini deleted file mode 100755 index 3cc059e92f320d602150c4cd9976cc0f946eb16e..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_dnn/pic/desktop.ini +++ /dev/null @@ -1,6 +0,0 @@ -[LocalizedFileNames] -image-20250919181207847-20260428155154-uzwemxm.png=@image-20250919181207847-20260428155154-uzwemxm.png,0 -image-20251015164912907-20260428155154-2xsyked.png=@image-20251015164912907-20260428155154-2xsyked.png,0 -image-20251015165024778-20260428155154-q7q5nwd.png=@image-20251015165024778-20260428155154-q7q5nwd.png,0 -image-20251231154118407-20260428155154-wuxs2ae.png=@image-20251231154118407-20260428155154-wuxs2ae.png,0 -image-20251231154144577-20260428155154-2v7swub.png=@image-20251231154144577-20260428155154-2v7swub.png,0 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20221114150205685-20260428155154-4qvikeh.png b/vendor/zsks/demo/opencv_dnn/pic/image-20221114150205685-20260428155154-4qvikeh.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20250919151018659-20260428155154-hmsqk38.png b/vendor/zsks/demo/opencv_dnn/pic/image-20250919151018659-20260428155154-hmsqk38.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20250919151519310-20260428155154-pcw91eu.png b/vendor/zsks/demo/opencv_dnn/pic/image-20250919151519310-20260428155154-pcw91eu.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20250919181207847-20260428155154-uzwemxm.png b/vendor/zsks/demo/opencv_dnn/pic/image-20250919181207847-20260428155154-uzwemxm.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20250919183224310-20260428155154-m30s86i.png b/vendor/zsks/demo/opencv_dnn/pic/image-20250919183224310-20260428155154-m30s86i.png old mode 100755 new mode 100644 index b539dd4175d5937062827ba614b2993165d510e4..e2f03fa623719b31204494600d16742f1e223934 Binary files a/vendor/zsks/demo/opencv_dnn/pic/image-20250919183224310-20260428155154-m30s86i.png and b/vendor/zsks/demo/opencv_dnn/pic/image-20250919183224310-20260428155154-m30s86i.png differ diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251015164912907-20260428155154-2xsyked.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251015164912907-20260428155154-2xsyked.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251015165024778-20260428155154-q7q5nwd.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251015165024778-20260428155154-q7q5nwd.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251023112130092-20260428155154-cqh1n3p.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251023112130092-20260428155154-cqh1n3p.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251023112228717-20260428155154-6u098o8.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251023112228717-20260428155154-6u098o8.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251023112328619-20260428155154-wc95wvm.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251023112328619-20260428155154-wc95wvm.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251023112352692-20260428155154-c4gqzws.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251023112352692-20260428155154-c4gqzws.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251023112451423-20260428155154-jeei5hl.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251023112451423-20260428155154-jeei5hl.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251231154118407-20260428155154-wuxs2ae.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251231154118407-20260428155154-wuxs2ae.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20251231154144577-20260428155154-2v7swub.png b/vendor/zsks/demo/opencv_dnn/pic/image-20251231154144577-20260428155154-2v7swub.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/opencv_dnn/pic/image-20260428150712-7avg3km.png old mode 100755 new mode 100644 index df435036941a44a6cb7417ceb227de759f7b23b7..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files a/vendor/zsks/demo/opencv_dnn/pic/image-20260428150712-7avg3km.png and b/vendor/zsks/demo/opencv_dnn/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151316-vwbp8qg.png b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151316-vwbp8qg.png old mode 100755 new mode 100644 index 15f31ab2465ae782b7f989394636f63afb3adf56..d9685f02d7410d1873f90b5b2cc0280f159f26aa Binary files a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151316-vwbp8qg.png and b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151316-vwbp8qg.png differ diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151432-6nzax2h.png b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151432-6nzax2h.png old mode 100755 new mode 100644 index d5caadbf1182a680d8500a5231e60f7e545caf88..a3fac08b2fef75aaa6d7d1e9bf5fb045e029ce82 Binary files a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151432-6nzax2h.png and b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151432-6nzax2h.png differ diff --git a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151528-smzz9s8.png b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151528-smzz9s8.png old mode 100755 new mode 100644 index 77a7bef4a3847c61c98449b68dad4c61fb494d0c..5aeccc9c51038fd22fcc550a3e6c8a5039edb32e Binary files a/vendor/zsks/demo/opencv_dnn/pic/image-20260428151528-smzz9s8.png and b/vendor/zsks/demo/opencv_dnn/pic/image-20260428151528-smzz9s8.png differ diff --git a/vendor/zsks/demo/opencv_ive/001.dilate/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/001.dilate/CMakeLists.txt deleted file mode 100755 index 04615d13c96898092b87ea6f77490e0138517f7c..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/001.dilate/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# 声明cmake解释器的最低版本 -cmake_minimum_required(VERSION 3.16) - -project(demo) -# 添加调试标志 -set(CMAKE_BUILD_TYPE Debug) - -################################################################################ -# 优化后的OpenCV库 - set(OpenCV_DIR "$ENV{dir_for_install_opencv_on_cloud}/lib/cmake/opencv4") -# 设置OpenCV路径 -find_package(OpenCV REQUIRED) - - -# 头文件到哪里去找 -include_directories( - "${OpenCV_INCLUDE_DIRS}" - "$ENV{dir_for_log_lib}" - ) -# 库文件到哪个目录去找? -link_directories( - "$ENV{dir_for_install_opencv_on_cloud}/lib" -) -link_libraries("${OpenCV_LIBS}") - - -add_executable(demo - demo.cpp - ) \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/001.dilate/demo.cpp b/vendor/zsks/demo/opencv_ive/001.dilate/demo.cpp deleted file mode 100755 index 7fe7479b6f8169840e10a2957247102a844352a7..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/001.dilate/demo.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include - -using namespace cv; -using namespace std; - -void cust_stat(const char* title,double t=0){ - static int counter=0; - static double times[2]={0,0}; - if(t>0){ - times[counter++]=t; - return; - } - printf("\n"); - double before=times[0]; - double after=times[1]; - double effect=before/after; - printf("%s,加速前,%f,加速后,%f,加速比,%f\n",title,before,after,effect); - printf("\n"); -} - - -// 定义图像元数据 -int width = 640; -int height = 480; - -// 生成随机图像,不使用OpenCV API -std::shared_ptr gen_random_img(int width, int height) { - // 创建Mat对象,但不使用OpenCV API填充数据 - auto result = std::make_shared(height, width, CV_8UC1); - uchar* data = result->ptr(0); - int total_pixels = width * height; - - for (int i = 0; i < total_pixels; i++) { - data[i] = (rand() % 2) ? 255 : 0; - } - - return result; -} - -// 验证膨胀操作,不使用OpenCV API -bool validateDilate(const Mat& img, const Mat& result, const Mat& kernel) { - if (img.size() != result.size()) { - cerr << "错误:图像尺寸不匹配" << endl; - return false; - } - - // 获取核的尺寸和中心位置 - int kernel_rows = kernel.rows; - int kernel_cols = kernel.cols; - int anchor_x = kernel_cols / 2; - int anchor_y = kernel_rows / 2; - - // 获取图像数据指针 - const uchar* img_data = img.ptr(0); - const uchar* result_data = result.ptr(0); - int img_step = img.step1(); - int result_step = result.step1(); - - // 手动实现膨胀操作进行验证 - for (int r = 0; r < img.rows; r++) { - for (int c = 0; c < img.cols; c++) { - uchar max_val = 0; - - // 检查核覆盖区域内的最大值 - for (int i = -anchor_y; i <= kernel_rows - anchor_y - 1; i++) { - int row = r + i; - if (row < 0 || row >= img.rows) continue; - - for (int j = -anchor_x; j <= kernel_cols - anchor_x - 1; j++) { - int col = c + j; - if (col < 0 || col >= img.cols) continue; - - // 检查核元素是否为非零 - if (kernel.at(i + anchor_y, j + anchor_x) != 0) { - uchar pixel_val = img_data[row * img_step + col]; - if (pixel_val > max_val) { - max_val = pixel_val; - } - } - } - } - - // 比较结果 - uchar res_val = result_data[r * result_step + c]; - if (res_val != max_val) { - cerr << "验证失败:位置(" << r << "," << c << ") " - << "实际=" << (int)res_val << " 预期=" << (int)max_val << endl; - return false; - } - } - } - - cout << "膨胀操作验证通过" << endl; - return true; -} -//////////////////////////// - -//// - - -//// -void test_work(const char* hint, int counter = 1000) { - // 生成随机图像 - auto img = gen_random_img(width, height); - Mat result(height,width,CV_8UC1); - - // 创建膨胀核(3x3矩形) - // 这里使用OpenCV API创建核,但验证函数不使用OpenCV API - Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); - - // 开始计时 - spdlog::stopwatch sw; - int c = 0; - // 执行指定次数的测试 - while (++c <= counter) { - dilate(*img, result, kernel); - } - // 显示测试结果 - cust_stat("001",sw.elapsed().count()); - CUST_LOGGER_CRITICAL("{}, {}次耗时{}秒", hint, counter, sw.elapsed().count()); - // 验证膨胀结果 - validateDilate(*img, result, kernel); -} -/// -/// \return - -int main() { - // 开展测试 - printf("开始测试!\n"); - ::cust::enable(-1); - test_work("加速前的opencv默认实现"); - ::cust::enable(1); - test_work("加速后的ive实现"); - cust_stat("001"); - return 0; -} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/001_dilate_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/001_dilate_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/001_dilate_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/001_dilate_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/001_dilate_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71140b3d6fa80b7eed024c6950e5935fe08ca8ce --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/001_dilate_demo/main_for_cxx.cpp @@ -0,0 +1,161 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int MORPH_KERNEL_SIZE = 3; +constexpr int BENCH_ITERATIONS = 1000; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +std::shared_ptr GenRandomImg(int width, int height) +{ + auto result = std::make_shared(height, width, CV_8UC1); + uchar* data = result->ptr(0); + int total_pixels = width * height; + + for (int i = 0; i < total_pixels; i++) { + data[i] = (rand() % RANDOM_BINARY_MODULO) ? GRAY_MAX : BINARY_MIN; + } + + return result; +} + +static uchar CalculateDilatedPixel(const Mat& img, const Mat& kernel, int r, int c) +{ + int kernel_rows = kernel.rows; + int kernel_cols = kernel.cols; + int anchor_x = kernel_cols / 2; + int anchor_y = kernel_rows / 2; + const uchar* imgData = img.ptr(0); + int img_step = img.step1(); + uchar maxVal = BINARY_MIN; + int row_begin = std::max(0, r - anchor_y); + int row_end = std::min(img.rows, r + kernel_rows - anchor_y); + int col_begin = std::max(0, c - anchor_x); + int col_end = std::min(img.cols, c + kernel_cols - anchor_x); + + for (int row = row_begin; row < row_end; row++) { + int kernel_row = row - r + anchor_y; + + for (int col = col_begin; col < col_end; col++) { + int kernel_col = col - c + anchor_x; + if (kernel.at(kernel_row, kernel_col) == 0) { + continue; + } + + uchar pixelVal = imgData[row * img_step + col]; + if (pixelVal > maxVal) { + maxVal = pixelVal; + } + } + } + + return maxVal; +} + +bool ValidateDilate(const Mat& img, const Mat& result, const Mat& kernel) +{ + if (img.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + const uchar* resultData = result.ptr(0); + int result_step = result.step1(); + + for (int r = 0; r < img.rows; r++) { + for (int c = 0; c < img.cols; c++) { + uchar maxVal = CalculateDilatedPixel(img, kernel, r, c); + uchar resVal = resultData[r * result_step + c]; + if (resVal != maxVal) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) resVal << " 预期=" << (int) maxVal << endl; + return false; + } + } + } + + cout << "膨胀操作验证通过" << endl; + return true; +} + +static void test_work(const char* hint, int counter = BENCH_ITERATIONS) +{ + auto img = GenRandomImg(IMAGE_WIDTH, IMAGE_HEIGHT); + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + Mat kernel = getStructuringElement(MORPH_RECT, Size(MORPH_KERNEL_SIZE, MORPH_KERNEL_SIZE)); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + dilate(*img, result, kernel); + } + cust_stat("001_dilate_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{}, {}次耗时{}秒", hint, counter, sw.elapsed().count()); + ValidateDilate(*img, result, kernel); +} + +int main() +{ + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("001_dilate_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/002.erode/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/002.erode/CMakeLists.txt deleted file mode 100755 index 04615d13c96898092b87ea6f77490e0138517f7c..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/002.erode/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# 声明cmake解释器的最低版本 -cmake_minimum_required(VERSION 3.16) - -project(demo) -# 添加调试标志 -set(CMAKE_BUILD_TYPE Debug) - -################################################################################ -# 优化后的OpenCV库 - set(OpenCV_DIR "$ENV{dir_for_install_opencv_on_cloud}/lib/cmake/opencv4") -# 设置OpenCV路径 -find_package(OpenCV REQUIRED) - - -# 头文件到哪里去找 -include_directories( - "${OpenCV_INCLUDE_DIRS}" - "$ENV{dir_for_log_lib}" - ) -# 库文件到哪个目录去找? -link_directories( - "$ENV{dir_for_install_opencv_on_cloud}/lib" -) -link_libraries("${OpenCV_LIBS}") - - -add_executable(demo - demo.cpp - ) \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/002.erode/demo.cpp b/vendor/zsks/demo/opencv_ive/002.erode/demo.cpp deleted file mode 100755 index 7cb2859141ad1c72e10ccfc10e52ff5708abe66b..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/002.erode/demo.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include -#include - -using namespace cv; -using namespace std; - - -void cust_stat(const char* title,double t=0){ - static int counter=0; - static double times[2]={0,0}; - if(t>0){ - times[counter++]=t; - return; - } - printf("\n"); - double before=times[0]; - double after=times[1]; - double effect=before/after; - printf("%s,加速前,%f,加速后,%f,加速比,%f\n",title,before,after,effect); - printf("\n"); -} - -// 定义图像元数据 -int width = 640; -int height = 480; - -// 生成随机图像,不使用OpenCV API -std::shared_ptr gen_random_img(int width, int height) { - // 创建Mat对象,但不使用OpenCV API填充数据 - auto result = std::make_shared(height, width, CV_8UC1); - uchar* data = result->ptr(0); - int total_pixels = width * height; - - for (int i = 0; i < total_pixels; i++) { - data[i] = (rand() % 2) ? 255 : 0; - } - - return result; -} - -// 验证腐蚀操作,不使用OpenCV API -bool validateErode(const Mat& img, const Mat& result, const Mat& kernel) { - if (img.size() != result.size()) { - cerr << "错误:图像尺寸不匹配" << endl; - return false; - } - - // 获取核的尺寸和中心位置 - int kernel_rows = kernel.rows; - int kernel_cols = kernel.cols; - int anchor_x = kernel_cols / 2; - int anchor_y = kernel_rows / 2; - - // 获取图像数据指针 - const uchar* img_data = img.ptr(0); - const uchar* result_data = result.ptr(0); - int img_step = img.step1(); - int result_step = result.step1(); - - // 手动实现腐蚀操作进行验证 - for (int r = 0; r < img.rows; r++) { - for (int c = 0; c < img.cols; c++) { - uchar min_val = 255; // 初始设为最大值 - bool all_covered = true; // 检查核是否完全在图像内 - - // 检查核覆盖区域内的最小值 - for (int i = -anchor_y; i <= kernel_rows - anchor_y - 1; i++) { - int row = r + i; - if (row < 0 || row >= img.rows) { - all_covered = false; - continue; - } - - for (int j = -anchor_x; j <= kernel_cols - anchor_x - 1; j++) { - int col = c + j; - if (col < 0 || col >= img.cols) { - all_covered = false; - continue; - } - - // 检查核元素是否为非零 - if (kernel.at(i + anchor_y, j + anchor_x) != 0) { - uchar pixel_val = img_data[row * img_step + col]; - if (pixel_val < min_val) { - min_val = pixel_val; - } - } - } - } - - // 如果核不完全在图像内,OpenCV的行为是边界处理,这里简化处理 - if (!all_covered) { - // 对于边界情况,我们简化处理,不进行详细验证 - continue; - } - - // 比较结果 - uchar res_val = result_data[r * result_step + c]; - if (res_val != min_val) { - cerr << "验证失败:位置(" << r << "," << c << ") " - << "实际=" << (int)res_val << " 预期=" << (int)min_val << endl; - return false; - } - } - } - - cout << "腐蚀操作验证通过" << endl; - return true; -} -///// - - -///// - - -void test_work(const char* hint, int counter = 1000) { - // 生成随机图像 - auto img = gen_random_img(width, height); - Mat result(height,width,CV_8UC1); - - // 创建腐蚀核(3x3矩形) - // 这里使用OpenCV API创建核,但验证函数不使用OpenCV API - Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); - - // 开始计时 - spdlog::stopwatch sw; - int c = 0; - // 执行指定次数的测试 - while (++c <= counter) { - erode(*img, result, kernel); - } - // 显示测试结果 - cust_stat("002",sw.elapsed().count()); - CUST_LOGGER_CRITICAL("{}, {}次耗时{}秒", hint, counter, sw.elapsed().count()); - // 验证腐蚀结果 - validateErode(*img, result, kernel); -} - -///////////////////////////////// -//// - - -/// -/// \return - -int main() { - // 开展测试 - printf("开始测试腐蚀操作!\n"); - ::cust::enable(-1); - test_work("腐蚀操作-加速前的opencv默认实现"); - ::cust::enable(1); - test_work("腐蚀操作-加速后的ive实现"); - cust_stat("002"); - return 0; -} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/002_erode_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/002_erode_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/002_erode_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/002_erode_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/002_erode_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a78cf029b57675bf9098ddd387f00dcd63f79b1d --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/002_erode_demo/main_for_cxx.cpp @@ -0,0 +1,175 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int MORPH_KERNEL_SIZE = 3; +constexpr int BENCH_ITERATIONS = 1000; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +std::shared_ptr GenRandomImg(int width, int height) +{ + auto result = std::make_shared(height, width, CV_8UC1); + uchar* data = result->ptr(0); + int total_pixels = width * height; + + for (int i = 0; i < total_pixels; i++) { + data[i] = (rand() % RANDOM_BINARY_MODULO) ? GRAY_MAX : BINARY_MIN; + } + + return result; +} + +static inline bool HasFullKernelCoverage(int r, int c, const Mat& img, const Mat& kernel) +{ + int anchor_x = kernel.cols / 2; + int anchor_y = kernel.rows / 2; + return r - anchor_y >= 0 && r + kernel.rows - anchor_y <= img.rows && + c - anchor_x >= 0 && c + kernel.cols - anchor_x <= img.cols; +} + +static uchar CalculateErodedPixel(const Mat& img, const Mat& kernel, int r, int c) +{ + int kernel_rows = kernel.rows; + int kernel_cols = kernel.cols; + int anchor_x = kernel_cols / 2; + int anchor_y = kernel_rows / 2; + const uchar* imgData = img.ptr(0); + int img_step = img.step1(); + uchar minVal = GRAY_MAX; + + for (int i = 0; i < kernel_rows; ++i) { + for (int j = 0; j < kernel_cols; ++j) { + if (kernel.at(i, j) == 0) { + continue; + } + + int row = r + i - anchor_y; + int col = c + j - anchor_x; + uchar pixelVal = imgData[row * img_step + col]; + if (pixelVal < minVal) { + minVal = pixelVal; + } + } + } + + return minVal; +} + +bool ValidateErode(const Mat& img, const Mat& result, const Mat& kernel) +{ + if (img.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + int kernel_rows = kernel.rows; + int kernel_cols = kernel.cols; + int anchor_x = kernel_cols / 2; + int anchor_y = kernel_rows / 2; + + const uchar* imgData = img.ptr(0); + const uchar* resultData = result.ptr(0); + int img_step = img.step1(); + int result_step = result.step1(); + + for (int r = 0; r < img.rows; r++) { + for (int c = 0; c < img.cols; c++) { + if (!HasFullKernelCoverage(r, c, img, kernel)) { + continue; + } + + uchar minVal = CalculateErodedPixel(img, kernel, r, c); + uchar resVal = resultData[r * result_step + c]; + if (resVal != minVal) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) resVal << " 预期=" << (int) minVal << endl; + return false; + } + } + } + + cout << "腐蚀操作验证通过" << endl; + return true; +} + +static void test_work(const char* hint, int counter = BENCH_ITERATIONS) +{ + auto img = GenRandomImg(IMAGE_WIDTH, IMAGE_HEIGHT); + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + Mat kernel = getStructuringElement(MORPH_RECT, Size(MORPH_KERNEL_SIZE, MORPH_KERNEL_SIZE)); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + erode(*img, result, kernel); + } + cust_stat("002_erode_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{}, {}次耗时{}秒", hint, counter, sw.elapsed().count()); + ValidateErode(*img, result, kernel); +} + +int main() +{ + // 开展测试 + printf("开始测试腐蚀操作!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("腐蚀操作-加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("腐蚀操作-加速后的ive实现"); + cust_stat("002_erode_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/003.sobel_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/003.sobel_demo/CMakeLists.txt deleted file mode 100755 index 04615d13c96898092b87ea6f77490e0138517f7c..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/003.sobel_demo/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# 声明cmake解释器的最低版本 -cmake_minimum_required(VERSION 3.16) - -project(demo) -# 添加调试标志 -set(CMAKE_BUILD_TYPE Debug) - -################################################################################ -# 优化后的OpenCV库 - set(OpenCV_DIR "$ENV{dir_for_install_opencv_on_cloud}/lib/cmake/opencv4") -# 设置OpenCV路径 -find_package(OpenCV REQUIRED) - - -# 头文件到哪里去找 -include_directories( - "${OpenCV_INCLUDE_DIRS}" - "$ENV{dir_for_log_lib}" - ) -# 库文件到哪个目录去找? -link_directories( - "$ENV{dir_for_install_opencv_on_cloud}/lib" -) -link_libraries("${OpenCV_LIBS}") - - -add_executable(demo - demo.cpp - ) \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/003.sobel_demo/demo.cpp b/vendor/zsks/demo/opencv_ive/003.sobel_demo/demo.cpp deleted file mode 100755 index 871b9fa983e51ff3d1590346c99224341b5b46b4..0000000000000000000000000000000000000000 --- a/vendor/zsks/demo/opencv_ive/003.sobel_demo/demo.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include -#include - -void cust_stat(const char* title,double t=0){ - static int counter=0; - static double times[2]={0,0}; - if(t>0){ - times[counter++]=t; - return; - } - printf("\n"); - double before=times[0]; - double after=times[1]; - double effect=before/after; - printf("%s,加速前,%f,加速后,%f,加速比,%f\n",title,before,after,effect); - printf("\n"); -} -void save_mat_bin(const std::string& filename, const cv::Mat& mat) { - std::ofstream ofs(filename, std::ios::binary); - if (!ofs) { - throw std::runtime_error("Cannot open file: " + filename); - } - ofs.write((const char*)mat.data, mat.total() * mat.elemSize()); - ofs.close(); -} -void load_mat_bin(const std::string& filename, cv::Mat& mat){ - std::ifstream ifs(filename, std::ios::binary); - if (!ifs) { - throw std::runtime_error("Cannot open file: " + filename); - } - ifs.read((char*)mat.data, mat.total() * mat.elemSize()); - ifs.close(); -} -// 定义图像元数据 -int width = 720; -int height = 576; -static std::string cust_pick_input_path(const char* argv1_or_null) { - std::vector candidates; - - if (argv1_or_null != nullptr && argv1_or_null[0] != '\0') { - candidates.emplace_back(argv1_or_null); - } - - const char* env = std::getenv("CUST_DEMO_DATA_DIR"); - if (env != nullptr && env[0] != '\0') { - std::string base(env); - while (!base.empty() && base.back() == '/') base.pop_back(); - candidates.emplace_back(base + "/demo.png.yuv400"); - candidates.emplace_back(base + "/003.sobel_demo/demo.png.yuv400"); - } - - // 默认优先相对路径(以当前工作目录为基准) - candidates.emplace_back("demo.png.yuv400"); - candidates.emplace_back("003.sobel_demo/demo.png.yuv400"); - - for (const auto& p : candidates) { - std::ifstream ifs(p, std::ios::binary); - if (ifs.good()) return p; - } - - // 保留原错误信息形态,便于脚本/日志定位 - throw std::runtime_error("Cannot open file: " + candidates.front()); -} - -void test_work(const char* hint, int counter, const char* input_path_arg){ - // 定义三幅图像 - ::cv::Mat input(height, width, CV_8UC1); - const std::string input_path = cust_pick_input_path(input_path_arg); - load_mat_bin(input_path, input); - ::cv::Mat output_hor(height, width, CV_16SC1); - ::cv::Mat output_ver(height, width, CV_16SC1); - // 加载数据 - // 开始计时 - spdlog::stopwatch sw; - int c=0; - // 执行指定次数的测试 - while(++c<=counter){ - // 计算 x 方向的梯度 - cv::Sobel(input, output_hor, CV_16S, 1, 0, 3, 1, 0, cv::BORDER_DEFAULT); - // 计算 y 方向的梯度 - cv::Sobel(input, output_ver, CV_16S, 0, 1, 3, 1, 0, cv::BORDER_DEFAULT); - } - // 显示测试结果 - cust_stat("003",sw.elapsed().count()); - CUST_LOGGER_CRITICAL("{},{}次耗时{}秒",hint,counter,sw.elapsed().count()); - //把output_hor和output_ver保存到文件中 - ::std::string prefix=hint; - save_mat_bin(prefix+"_hor.bin",output_hor); - save_mat_bin(prefix+"_ver.bin",output_ver); -} - -int main(int argc, char** argv){ - const char* input_path = (argc >= 2) ? argv[1] : nullptr; - // 开展测试 - printf("开始测试!\n"); - ::cust::enable(-1); - test_work("加速前的opencv默认实现", 100, input_path); - ::cust::enable(1); - test_work("加速后的ive实现", 100, input_path); - cust_stat("003"); - return 0; -} - -/* --exec set solib-search-path /workdir/build4opencv/lib -*/ \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/003_sobel_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/003_sobel_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a5f9ce9db48dd74490b451b38ab3a565ea94cff6 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/003_sobel_demo/CMakeLists.txt @@ -0,0 +1,16 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体与源码目录下的 demo.png.yuv400 到同一子目录(与 elf 并列) +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name}) +# 7.安装数据文件和执行体放到相同的目录 +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/demo_png.yuv400" DESTINATION ${sub_project_name}) diff --git a/vendor/zsks/demo/opencv_ive/003.sobel_demo/demo.png.yuv400 b/vendor/zsks/demo/opencv_ive/003_sobel_demo/demo_png.yuv400 old mode 100755 new mode 100644 similarity index 100% rename from vendor/zsks/demo/opencv_ive/003.sobel_demo/demo.png.yuv400 rename to vendor/zsks/demo/opencv_ive/003_sobel_demo/demo_png.yuv400 diff --git a/vendor/zsks/demo/opencv_ive/003_sobel_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/003_sobel_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a6f5abef7d4afbbf73a32f2279396f05fe51f7d --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/003_sobel_demo/main_for_cxx.cpp @@ -0,0 +1,147 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 720; +constexpr int IMAGE_HEIGHT = 576; +constexpr int SOBEL_DX_HOR = 1; +constexpr int SOBEL_DY_HOR = 0; +constexpr int SOBEL_DX_VER = 0; +constexpr int SOBEL_DY_VER = 1; +constexpr int SOBEL_KERNEL_SIZE = 3; +constexpr int SOBEL_SCALE = 1; +constexpr int SOBEL_DELTA = 0; +constexpr int BENCH_ITERATIONS = 100; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[4096]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +void save_mat_bin(const std::string& filename, const cv::Mat& mat) +{ + std::ofstream ofs(filename, std::ios::binary); + if (!ofs) { + throw std::runtime_error("Cannot open file: " + filename); + } + ofs.write((const char*) mat.data, mat.total() * mat.elemSize()); + ofs.close(); +} +void load_mat_bin(const std::string& filename, cv::Mat& mat) +{ + std::ifstream ifs(filename, std::ios::binary); + if (!ifs) { + throw std::runtime_error("Cannot open file: " + filename); + } + ifs.read((char*) mat.data, mat.total() * mat.elemSize()); + ifs.close(); +} +void test_work(const char* hint, int counter = BENCH_ITERATIONS) +{ + // 定义三幅图像 + ::cv::Mat input(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + load_mat_bin(g_elf_dir + "/demo_png.yuv400", input); + ::cv::Mat output_hor(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16SC1); + ::cv::Mat output_ver(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16SC1); + // 加载数据 + // 开始计时 + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + // 计算 x 方向的梯度 + cv::Sobel(input, + output_hor, + CV_16S, + SOBEL_DX_HOR, + SOBEL_DY_HOR, + SOBEL_KERNEL_SIZE, + SOBEL_SCALE, + SOBEL_DELTA, + cv::BORDER_DEFAULT); + // 计算 y 方向的梯度 + cv::Sobel(input, + output_ver, + CV_16S, + SOBEL_DX_VER, + SOBEL_DY_VER, + SOBEL_KERNEL_SIZE, + SOBEL_SCALE, + SOBEL_DELTA, + cv::BORDER_DEFAULT); + } + // 显示测试结果 + cust_stat("003_sobel_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + // 把output_hor和output_ver保存到文件中 + ::std::string prefix = hint; + save_mat_bin(g_elf_dir + "/" + prefix + "_hor.bin", output_hor); + save_mat_bin(g_elf_dir + "/" + prefix + "_ver.bin", output_ver); +} + +int main() +{ + init_elf_dir(); + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("003_sobel_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/004_bin_and_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/004_bin_and_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/004_bin_and_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/004_bin_and_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/004_bin_and_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b167b29bbec55369e67789e76257970ffeea43d --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/004_bin_and_demo/main_for_cxx.cpp @@ -0,0 +1,128 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +::std::shared_ptr<::cv::Mat> gen_random_img(int width, int height) +{ + auto result = ::std::make_shared<::cv::Mat>(height, width, CV_8UC1); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + result->at(i, j) = (rand() % RANDOM_BINARY_MODULO) ? GRAY_MAX : BINARY_MIN; + } + } + return result; +} + +bool validateBitwiseAnd(const Mat& img1, const Mat& img2, const Mat& result) +{ + if (img1.size() != img2.size() || img1.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + for (int r = 0; r < result.rows; r++) { + for (int c = 0; c < result.cols; c++) { + uchar p1 = img1.at(r, c); + uchar p2 = img2.at(r, c); + uchar res = result.at(r, c); + + // 验证相与逻辑:仅当两图对应像素均为255时结果才为255 + uchar expected = ((p1 == GRAY_MAX) && (p2 == GRAY_MAX)) ? GRAY_MAX : BINARY_MIN; + + if (res != expected) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) res << " 预期=" << (int) expected << " (输入值: " << (int) p1 << "," + << (int) p2 << ")" << endl; + return false; + } + } + } + cout << "通过验证" << endl; + return true; +} + +void test_work(const char* hint, int counter = 3000) +{ + // 生成两幅随机图 + auto img1 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + auto img2 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + ::cv::Mat result; + // 开始计时 + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + // 2.用opencv来算 + bitwise_and(*img1, *img2, result); + } + // 显示测试结果 + cust_stat("004_bin_and_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + // 3.自己核对一遍 + validateBitwiseAnd(*img1, *img2, result); +} + +int main() +{ + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("004_bin_and_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/005_bin_or_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/005_bin_or_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/005_bin_or_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/005_bin_or_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/005_bin_or_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e928cf82e756bc82dc26ddf36e9a979690b6d146 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/005_bin_or_demo/main_for_cxx.cpp @@ -0,0 +1,127 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +::std::shared_ptr<::cv::Mat> gen_random_img(int width, int height) +{ + auto result = ::std::make_shared<::cv::Mat>(height, width, CV_8UC1); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + result->at(i, j) = (rand() % RANDOM_BINARY_MODULO) ? GRAY_MAX : BINARY_MIN; + } + } + return result; +} + +bool validateBitwiseOr(const Mat& img1, const Mat& img2, const Mat& result) +{ + if (img1.size() != img2.size() || img1.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + for (int r = 0; r < result.rows; r++) { + for (int c = 0; c < result.cols; c++) { + uchar p1 = img1.at(r, c); + uchar p2 = img2.at(r, c); + uchar res = result.at(r, c); + + uchar expected = ((p1 == GRAY_MAX) || (p2 == GRAY_MAX)) ? GRAY_MAX : BINARY_MIN; + + if (res != expected) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) res << " 预期=" << (int) expected << " (输入值: " << (int) p1 << "," + << (int) p2 << ")" << endl; + return false; + } + } + } + cout << "通过验证" << endl; + return true; +} + +void test_work(const char* hint, int counter = 3000) +{ + // 生成两幅随机图 + auto img1 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + auto img2 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + ::cv::Mat result; + // 开始计时 + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + // 2.用opencv来算 + bitwise_or(*img1, *img2, result); + } + // 显示测试结果 + cust_stat("005_bin_or_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + // 3.自己核对一遍 + validateBitwiseOr(*img1, *img2, result); +} + +int main() +{ + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("005_bin_or_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32b37e12cd589314f27d5f719891dc59a0864904 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/006_bin_xor_demo/main_for_cxx.cpp @@ -0,0 +1,126 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +::std::shared_ptr<::cv::Mat> gen_random_img(int width, int height) +{ + auto result = ::std::make_shared<::cv::Mat>(height, width, CV_8UC1); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + result->at(i, j) = (rand() % RANDOM_BINARY_MODULO) ? GRAY_MAX : BINARY_MIN; + } + } + return result; +} + +bool validateBitwiseXor(const Mat& img1, const Mat& img2, const Mat& result) +{ + if (img1.size() != img2.size() || img1.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + for (int r = 0; r < result.rows; r++) { + for (int c = 0; c < result.cols; c++) { + uchar p1 = img1.at(r, c); + uchar p2 = img2.at(r, c); + uchar res = result.at(r, c); + + uchar expected = (p1 == p2) ? BINARY_MIN : GRAY_MAX; + + if (res != expected) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) res << " 预期=" << (int) expected << " (输入值: " << (int) p1 << "," + << (int) p2 << ")" << endl; + return false; + } + } + } + cout << "通过验证" << endl; + return true; +} + +void test_work(const char* hint, int counter = 3000) +{ + // 生成两幅随机图 + auto img1 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + auto img2 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + ::cv::Mat result; + // 开始计时 + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + // 2.用opencv来算 + bitwise_xor(*img1, *img2, result); + } + // 显示测试结果 + cust_stat("006_bin_xor_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + // 3.自己核对一遍 + validateBitwiseXor(*img1, *img2, result); +} + +int main() +{ + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("006_bin_xor_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..066164ce82afb5ce113706af1bd126ec9fec4333 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/007_bin_sub_demo/main_for_cxx.cpp @@ -0,0 +1,122 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 640; +constexpr int IMAGE_HEIGHT = 480; +constexpr int GRAY_LEVEL_COUNT = 256; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +::std::shared_ptr<::cv::Mat> gen_random_img(int width, int height) +{ + auto result = ::std::make_shared<::cv::Mat>(height, width, CV_8UC1); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + result->at(i, j) = static_cast(rand() % GRAY_LEVEL_COUNT); + } + } + return result; +} + +bool validateBitwiseSub(const Mat& img1, const Mat& img2, const Mat& result) +{ + if (img1.size() != img2.size() || img1.size() != result.size()) { + cerr << "错误:图像尺寸不匹配" << endl; + return false; + } + + for (int r = 0; r < result.rows; r++) { + for (int c = 0; c < result.cols; c++) { + uchar p1 = img1.at(r, c); + uchar p2 = img2.at(r, c); + uchar res = result.at(r, c); + uchar expected = abs(p1 - p2); + if (res != expected) { + cerr << "验证失败:位置(" << r << "," << c << ") " + << "实际=" << (int) res << " 预期=" << (int) expected << " (输入值: " << (int) p1 << "," + << (int) p2 << ")" << endl; + return false; + } + } + } + cout << "通过验证" << endl; + return true; +} + +void test_work(const char* hint, int counter = 3000) +{ + // 生成两幅随机图 + auto img1 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + auto img2 = gen_random_img(IMAGE_WIDTH, IMAGE_HEIGHT); + ::cv::Mat result; + // 开始计时 + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + // 2.用opencv来算:这是我们优化的目标 + absdiff(*img1, *img2, result); + } + // 显示测试结果 + cust_stat("007_bin_sub_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + // 3.自己核对一遍 + validateBitwiseSub(*img1, *img2, result); +} + +int main() +{ + // 开展测试 + printf("开始测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现"); + cust_stat("007_bin_sub_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/008_resize_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/008_resize_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/008_resize_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/008_resize_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/008_resize_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3e22b521ff3c9a429e2e9f9f0b69357eefcc8d1 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/008_resize_demo/main_for_cxx.cpp @@ -0,0 +1,150 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int SRC_WIDTH = 320; +constexpr int SRC_HEIGHT = 240; +constexpr int DST_WIDTH = 640; +constexpr int DST_HEIGHT = 480; +constexpr int BENCH_ITERATIONS = 100; +constexpr int RAND_GRAY_MIN = 0; +constexpr int RAND_GRAY_MAX = 256; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[4096]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +// 1. 定义图像尺寸 +::std::shared_ptr<::cv::Mat> gen_random_img() +{ + auto result = ::std::make_shared<::cv::Mat>(SRC_HEIGHT, SRC_WIDTH, CV_8UC1); + // 使用OpenCV的函数填充0-255的随机灰度值 + cv::randu(*result, cv::Scalar(RAND_GRAY_MIN), cv::Scalar(RAND_GRAY_MAX)); + std::cout << "已生成 " << SRC_WIDTH << "x" << SRC_HEIGHT << " 的随机源图像。" << std::endl; + return result; +} + +bool validateBitwiseSub(const Mat& dst_mat) +{ + // 验证输出尺寸是否正确 + bool result; + if (dst_mat.cols == DST_WIDTH && dst_mat.rows == DST_HEIGHT) { + std::cout << "尺寸验证: 成功" << std::endl; + result = true; + } else { + std::cout << "需要宽度" << DST_WIDTH << ";实际宽度是:" << dst_mat.cols << std::endl; + std::cout << "需要高度" << DST_HEIGHT << ";实际高度是:" << dst_mat.rows << std::endl; + std::cout << "尺寸验证: 失败" << std::endl; + result = false; + } + + ::std::string filename = g_elf_dir + "/resized_image_opencv.png"; + try { + if (cv::imwrite(filename, dst_mat)) { + std::cout << "已将放大后的图像保存到文件: " << filename << std::endl; + } else { + std::cerr << "错误: 无法保存图像文件。" << std::endl; + } + } catch (const cv::Exception& ex) { + std::cerr << "OpenCV 错误: " << ex.what() << std::endl; + } + return result; +} + +void test_work(const char* hint, Mat* input, int counter = BENCH_ITERATIONS) +{ + cv::Mat dst_mat(DST_HEIGHT, DST_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + // 执行指定次数的测试 + while (++c <= counter) { + cv::resize(*input, // 输入图像 + dst_mat, // 输出图像 + cv::Size(DST_WIDTH, DST_HEIGHT), // 目标尺寸 + 0, // fx, 水平缩放比例,设为0则由dsize计算 + 0, // fy, 垂直缩放比例,设为0则由dsize计算 + cv::INTER_LINEAR); // 插值方法:双线性插值 + } + // 显示测试结果 + cust_stat("008_resize_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + validateBitwiseSub(dst_mat); +} + +int main() +{ + init_elf_dir(); + // 开展测试 + printf("开始测试!\n"); + + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + auto input = gen_random_img(); + test_work("加速前的opencv默认实现", input.get()); + + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现", input.get()); + cust_stat("008_resize_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/009_ncc_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/009_ncc_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/009_ncc_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/009_ncc_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/009_ncc_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7bdf072acb0fbb0d9589abcb55709fb617bdc08 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/009_ncc_demo/main_for_cxx.cpp @@ -0,0 +1,182 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include +namespace cust::mpp::ive { +// 用来表示初始化工作,有没有完成 +bool inited(); +} // namespace cust::mpp::ive + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 256; +constexpr int IMAGE_HEIGHT = 256; +constexpr int GRAY_MIN = 0; +constexpr int GRAY_MAX = 255; +constexpr int BENCH_ITERATIONS = 100; +constexpr double K_DENOM_EPSILON = 1e-6; +constexpr int LOG_PRECISION_INTEGER = 0; +constexpr int NCC_DISPLAY_PRECISION = 8; +constexpr double K_NCC_VALUE_MIN = -1.0; +constexpr double K_NCC_VALUE_MAX = 1.0; +constexpr double K_NCC_RANGE_EPSILON = 0.0001; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +// 1. 定义图像尺寸常量 +using CustMat = std::shared_ptr; + +void gen_two_random_imgs(CustMat& src1, CustMat& src2) +{ + // 创建Mat对象但不使用OpenCV API填充数据 + src1 = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + src2 = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 获取指向图像数据的指针 + uint8_t* data1 = src1->data; + uint8_t* data2 = src2->data; + + // 随机数生成器 + std::random_device rd; + std::mt19937 gen1(rd()); // 第一个图像的随机数生成器 + std::mt19937 gen2(rd()); // 第二个图像的随机数生成器(使用不同的种子) + std::uniform_int_distribution<> dis(GRAY_MIN, GRAY_MAX); + + // 填充第一个图像 + for (int i = 0; i < IMAGE_HEIGHT * IMAGE_WIDTH; ++i) { + data1[i] = static_cast(dis(gen1)); + } + + // 填充第二个图像 + for (int i = 0; i < IMAGE_HEIGHT * IMAGE_WIDTH; ++i) { + data2[i] = static_cast(dis(gen2)); + } +} + +/** + * @brief 验证NCC计算结果并以特定格式打印 + * * @param num 分子项 + * @param quad_sum1 分母项1 + * @param quad_sum2 分母项2 + * @param ncc_value 最终NCC值 + * @return true 验证通过 (NCC值在[-1, 1]范围内) + * @return false 验证失败 + */ +bool validate_ncc_result(double num, double quad_sum1, double quad_sum2, double ncc_value) +{ + std::cout << "--- 计算结果 ---" << std::endl; + // 使用 std::fixed 和 setprecision(0) 来完整显示大的整数值 + std::cout << std::fixed << std::setprecision(LOG_PRECISION_INTEGER); + std::cout << "Numerator (num): " << num << std::endl; + std::cout << "Denominator (quad_sum1): " << quad_sum1 << std::endl; + std::cout << "Denominator (quad_sum2): " << quad_sum2 << std::endl; + // 恢复精度用于显示NCC值 + std::cout << std::fixed << std::setprecision(NCC_DISPLAY_PRECISION) << "最终 NCC 值: " << ncc_value << + std::endl; + + // NCC的理论值域为[-1, 1],增加一个简单的范围检查 + if (ncc_value >= K_NCC_VALUE_MIN - K_NCC_RANGE_EPSILON && ncc_value <= K_NCC_VALUE_MAX + K_NCC_RANGE_EPSILON) { + std::cout << "值域验证: 成功" << std::endl; + return true; + } else { + std::cout << "值域验证: 失败" << std::endl; + return false; + } +} + +/** + * @brief NCC计算性能的核心测试函数 + * * @param hint 用于日志输出的描述性字符串 + * @param counter 核心操作的执行次数 + */ +// 对于快速操作,增加迭代次数 +void test_work(const char* hint, int a = -1, int counter = BENCH_ITERATIONS) +{ + // 准备输入数据 + CustMat src1; + CustMat src2; + gen_two_random_imgs(src1, src2); + + // 准备存放结果的变量 + double num = 0.0; + double quad_sum1 = 0.0; + double quad_sum2 = 0.0; + double ncc_value = 0.0; + // 启动计时器 + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑开始 --- + cv::ncc(*src1, *src2, num, quad_sum1, quad_sum2); + + ncc_value = 0.0; + if (quad_sum1 > 0 && quad_sum2 > 0) { + double denominator = sqrt(quad_sum1 * quad_sum2); + if (denominator > K_DENOM_EPSILON) { + ncc_value = num / denominator; + } + } + } + cust_stat("009_ncc_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务 + */ +int main() +{ + printf("开始 NCC (归一化互相关) 性能测试!\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + // 运行默认实现 + test_work("加速前的opencv默认实现 (NCC)"); + printf("\n"); // 增加一个换行,让输出更清晰 + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + // 运行IVE或其它加速实现 + test_work("加速后的ive实现 (NCC)", 1); + + cust_stat("009_ncc_demo"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/010_ccl_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/010_ccl_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/010_ccl_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/010_ccl_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/010_ccl_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bd4c3197aafeba8380bc04a0e05019a94fd43eb --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/010_ccl_demo/main_for_cxx.cpp @@ -0,0 +1,196 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include + +// 使用 using namespace +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 160; +constexpr int IMAGE_HEIGHT = 160; +constexpr int STRIPE_PERIOD = 15; +constexpr int STRIPE_WIDTH = 3; +constexpr int HOLE_COUNT = 20; +constexpr int CONNECTIVITY = 8; +constexpr unsigned int RNG_SEED = 12345; +constexpr int HOLE_RADIUS_MIN = 3; +constexpr int HOLE_RADIUS_MAX = 7; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; + +} // namespace + +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[4096]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +const std::string INPUT_IMAGE_PATH = "./010.ccl_demo/ccl_input.png"; + +static void draw_vertical_stripes(uint8_t* data) +{ + for (int x = 0; x < IMAGE_WIDTH; x += STRIPE_PERIOD) { + for (int line_offset = 0; line_offset < STRIPE_WIDTH; ++line_offset) { + int current_x = x + line_offset; + if (current_x >= IMAGE_WIDTH) { + break; + } + for (int y = 0; y < IMAGE_HEIGHT; ++y) { + data[y * IMAGE_WIDTH + current_x] = GRAY_MAX; + } + } + } +} + +static void draw_circle(uint8_t* data, int center_x, int center_y, int r) +{ + int r_sq = r * r; + for (int y = center_y - r; y <= center_y + r; ++y) { + for (int x = center_x - r; x <= center_x + r; ++x) { + if (y < 0 || y >= IMAGE_HEIGHT || x < 0 || x >= IMAGE_WIDTH) { + continue; + } + int dx = x - center_x; + int dy = y - center_y; + if (dx * dx + dy * dy <= r_sq) { + data[y * IMAGE_WIDTH + x] = BINARY_MIN; + } + } + } +} + +static void add_random_holes(uint8_t* data) +{ + std::mt19937 rng(RNG_SEED); + std::uniform_int_distribution radiusDist(HOLE_RADIUS_MIN, HOLE_RADIUS_MAX); + std::uniform_int_distribution xDist(0, IMAGE_WIDTH - 1); + std::uniform_int_distribution yDist(0, IMAGE_HEIGHT - 1); + + for (int i = 0; i < HOLE_COUNT; ++i) { + int r = radiusDist(rng); + int center_x = std::max(r, std::min(xDist(rng), IMAGE_WIDTH - r - 1)); + int center_y = std::max(r, std::min(yDist(rng), IMAGE_HEIGHT - r - 1)); + draw_circle(data, center_x, center_y, r); + } +} + +std::shared_ptr GenStripesHoles() +{ + auto img = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + uint8_t* data = img->data; + + for (int i = 0; i < IMAGE_HEIGHT * IMAGE_WIDTH; ++i) { + data[i] = BINARY_MIN; + } + + draw_vertical_stripes(data); + add_random_holes(data); + + return img; +} + +auto GenBinaryImg() -> std::shared_ptr +{ + return GenStripesHoles(); +} + +static void test_work(const char* hint, int counter = 100) +{ + auto input = GenBinaryImg(); + Mat labels(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + Mat stats; + Mat centroids; + int num_labels = 0; + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + num_labels = connectedComponentsWithStats(*input, labels, stats, centroids, CONNECTIVITY); + } + + cust_stat("010_ccl_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + cout << "连通区域数量为" << num_labels << endl; + + std::string fname(hint); + std::replace_if(fname.begin(), fname.end(), + [](char ch) { return ch == ':' || ch == '/' || ch == '\\' || ch == ' '; }, '_'); + fname += ".png"; + + Mat vis; + labels.convertTo(vis, CV_8UC1, static_cast(GRAY_MAX) / num_labels); + + fname = g_elf_dir + "/" + fname; + cv::imwrite(fname, vis); + cout << "labels 已保存为 " << fname << endl; +} + +int main() +{ + init_elf_dir(); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + printf("开始 CCL (连通域分析) 性能测试!\n"); + + test_work("opencv_CCL"); + + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("ive_CCL"); + cust_stat("010_ccl_demo"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/011_filter_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/011_filter_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/011_filter_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/011_filter_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/011_filter_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9ce2d9c96a0342bc05461c892cf61de922a84a8 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/011_filter_demo/main_for_cxx.cpp @@ -0,0 +1,205 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_SIZE = 512; +constexpr int RECT_X1 = 50; +constexpr int RECT_Y1 = 50; +constexpr int RECT_X2 = 200; +constexpr int RECT_Y2 = 200; +constexpr int CIRCLE_CENTER_X = 400; +constexpr int CIRCLE_CENTER_Y = 150; +constexpr int CIRCLE_RADIUS = 80; +constexpr int LINE_X1 = 300; +constexpr int LINE_Y1 = 400; +constexpr int LINE_X2 = 450; +constexpr int LINE_Y2 = 300; +constexpr int LINE_THICKNESS = 10; +constexpr int TEXT_X = 100; +constexpr int TEXT_Y = 400; +constexpr double K_TEXT_SCALE = 1.5; +constexpr int TEXT_THICKNESS = 3; +constexpr int GAUSSIAN_KERNEL_SIZE = 5; +constexpr int GRAY_MAX = 255; +constexpr int BINARY_MIN = 0; +constexpr double K_NOISE_RATIO = 0.04; +constexpr double K_GAUSSIAN_SIGMA_AUTO = 0; +constexpr int RANDOM_BINARY_MODULO = 2; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[4096]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +// 定义图像尺寸常量 +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +/** + * @brief 生成一个带有绘制图形和椒盐噪声的测试图像。 + * @param is_grayscale 如果为true,返回灰度图;否则返回彩色图。 + * @return 返回一个包含带噪声图像的智能指针。 + */ +auto gen_noisy_test_image(bool is_grayscale) -> std::shared_ptr +{ + // 1. 生成不带噪声的原始彩色图像 + Mat colorImg = Mat::zeros(IMAGE_SIZE, IMAGE_SIZE, CV_8UC3); + rectangle(colorImg, Point(RECT_X1, RECT_Y1), Point(RECT_X2, RECT_Y2), Scalar(0, GRAY_MAX, 0), FILLED); + circle(colorImg, Point(CIRCLE_CENTER_X, CIRCLE_CENTER_Y), CIRCLE_RADIUS, Scalar(GRAY_MAX, 0, 0), FILLED); + line(colorImg, Point(LINE_X1, LINE_Y1), Point(LINE_X2, LINE_Y2), Scalar(0, 0, GRAY_MAX), LINE_THICKNESS); + putText(colorImg, + "OpenCV", + Point(TEXT_X, TEXT_Y), + FONT_HERSHEY_SIMPLEX, + K_TEXT_SCALE, + Scalar(GRAY_MAX, GRAY_MAX, 0), + TEXT_THICKNESS); + + // 2. 根据需要决定是处理彩色图还是灰度图 + Mat baseImage; + if (is_grayscale) { + cvtColor(colorImg, baseImage, COLOR_BGR2GRAY); + } else { + baseImage = colorImg; + } + + // 3. 对图像添加椒盐噪声 + int noise_pixels = static_cast((IMAGE_SIZE * IMAGE_SIZE) * K_NOISE_RATIO); + for (int i = 0; i < noise_pixels; i++) { + int x = rand() % baseImage.cols; + int y = rand() % baseImage.rows; + + bool is_black_noise = (rand() % RANDOM_BINARY_MODULO == 0); + + if (baseImage.channels() == 1) { + // 灰度图 + baseImage.at(y, x) = is_black_noise ? BINARY_MIN : GRAY_MAX; + } else { + // 彩色图 + const Vec3b noiseColor = + is_black_noise ? Vec3b(BINARY_MIN, BINARY_MIN, BINARY_MIN) : Vec3b(GRAY_MAX, GRAY_MAX, GRAY_MAX); + baseImage.at(y, x) = noiseColor; + } + } + + return std::make_shared(baseImage); +} + +/** + * @brief 验证高斯滤波的结果,并保存噪声图和结果图。 + * @param noisy_img 带噪声的输入图像。 + * @param denoised_img 经过高斯滤波处理后的结果图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_gaussian_blur_result(const Mat& noisy_img, const Mat& denoised_img, const string& file_suffix) +{ + string noisy_filename = g_elf_dir + "/noisy_" + file_suffix + ".png"; + string denoised_filename = g_elf_dir + "/gaussian_blur_" + file_suffix + ".png"; + + imwrite(noisy_filename, noisy_img); + imwrite(denoised_filename, denoised_img); + + cout << "--- 结果已保存 ---" << endl; + cout << "已保存噪声图: " << noisy_filename << endl; + cout << "已保存高斯滤波结果图: " << denoised_filename << endl; + return true; +} + +/** + * @brief 高斯滤波性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param use_grayscale 指定测试使用灰度图还是彩色图。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, bool use_grayscale, int counter = 50) +{ + // 设置随机种子,确保每次测试生成的噪声图像都一样 + srand(0); + auto input = gen_noisy_test_image(use_grayscale); + + Mat result(IMAGE_SIZE, IMAGE_SIZE, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + GaussianBlur(*input, result, Size(GAUSSIAN_KERNEL_SIZE, GAUSSIAN_KERNEL_SIZE), K_GAUSSIAN_SIGMA_AUTO); + } + cust_stat("011_filter_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + validate_gaussian_blur_result(*input, result, file_suffix); +} + +int main() +{ + init_elf_dir(); + printf("开始 Gaussian Blur (高斯滤波) 性能测试!\n\n"); + printf("--- 开始测试灰度图 ---\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("灰度图加速前 (Gaussian Blur)", "gray_default", true); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("灰度图加速后 (Gaussian Blur)", "gray_ive", true); + cust_stat("011_filter_demo"); + printf("\n--- 测试完成 ---\n\n"); + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..984e98e33cd6d61ac14fe8d0e413072521f1065c --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/012_order_stats_filter_demo/main_for_cxx.cpp @@ -0,0 +1,199 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_SIZE = 512; +constexpr int BENCH_ITERATIONS = 100; +constexpr int MEDIAN_KERNEL_SIZE = 7; +constexpr int NOISE_SALT_THRESHOLD = 10; +constexpr int NOISE_PEPPER_THRESHOLD = 245; +constexpr int GRAY_MAX = 255; +constexpr int GRAY_MIN = 0; +constexpr int RECT_X1 = 50; +constexpr int RECT_Y1 = 50; +constexpr int RECT_X2 = 200; +constexpr int RECT_Y2 = 200; +constexpr int CIRCLE_CENTER_X = 400; +constexpr int CIRCLE_CENTER_Y = 150; +constexpr int CIRCLE_RADIUS = 80; +constexpr int LINE_X1 = 300; +constexpr int LINE_Y1 = 400; +constexpr int LINE_X2 = 450; +constexpr int LINE_Y2 = 300; +constexpr int LINE_THICKNESS = 10; +constexpr int TEXT_X = 100; +constexpr int TEXT_Y = 400; +constexpr double K_TEXT_SCALE = 1.5; +constexpr int TEXT_THICKNESS = 3; +constexpr int COLOR_GREEN = 0; +constexpr int COLOR_BLUE = 0; +constexpr int COLOR_RED = 255; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +auto gen_test_image(bool is_grayscale) -> std::shared_ptr +{ + // 1. 创建彩色图像并绘制元素 + auto colorImg = std::make_shared(IMAGE_SIZE, IMAGE_SIZE, CV_8UC3); + rectangle(*colorImg, + Point(RECT_X1, RECT_Y1), + Point(RECT_X2, RECT_Y2), + Scalar(COLOR_GREEN, GRAY_MAX, COLOR_GREEN), + FILLED); + circle(*colorImg, + Point(CIRCLE_CENTER_X, CIRCLE_CENTER_Y), + CIRCLE_RADIUS, + Scalar(GRAY_MAX, COLOR_GREEN, COLOR_BLUE), + FILLED); + line(*colorImg, + Point(LINE_X1, LINE_Y1), + Point(LINE_X2, LINE_Y2), + Scalar(COLOR_BLUE, COLOR_BLUE, GRAY_MAX), + LINE_THICKNESS); + putText(*colorImg, + "OpenCV", + Point(TEXT_X, TEXT_Y), + FONT_HERSHEY_SIMPLEX, + K_TEXT_SCALE, + Scalar(GRAY_MAX, GRAY_MAX, COLOR_GREEN), + TEXT_THICKNESS); + + // 2. 添加椒盐噪声 + Mat noise(IMAGE_SIZE, IMAGE_SIZE, CV_8UC1); + randu(noise, GRAY_MIN, GRAY_MAX); + for (int y = 0; y < IMAGE_SIZE; y++) { + for (int x = 0; x < IMAGE_SIZE; x++) { + uchar noise_val = noise.at(y, x); + if (noise_val < NOISE_SALT_THRESHOLD) { + colorImg->at(y, x) = Vec3b(GRAY_MIN, GRAY_MIN, GRAY_MIN); + } else if (noise_val > NOISE_PEPPER_THRESHOLD) { + colorImg->at(y, x) = Vec3b(GRAY_MAX, GRAY_MAX, GRAY_MAX); + } + } + } + + if (is_grayscale) { + auto grayImg = std::make_shared(); + cvtColor(*colorImg, *grayImg, COLOR_BGR2GRAY); + return grayImg; + } + + return colorImg; +} + +bool validate_median_blur_result(const Mat& original_img, const Mat& result_img, const string& file_suffix) +{ + // 构造文件名并保存 + string original_filename = g_elf_dir + "/original_" + file_suffix + ".png"; + string median_filename = g_elf_dir + "/median_blur_" + file_suffix + ".png"; + + imwrite(original_filename, original_img); + imwrite(median_filename, result_img); + + cout << "--- 结果已保存 ---" << endl; + cout << "已保存原始图: " << original_filename << endl; + cout << "已保存中值滤波结果图: " << median_filename << endl; + return true; +} + +void test_work(const char* hint, const string& file_suffix, bool use_grayscale, int counter = BENCH_ITERATIONS) +{ + auto input = gen_test_image(use_grayscale); + int width = input->cols; + int height = input->rows; + // 这个Mat用来接收计时循环中最后一次的计算结果 + Mat result(height, width, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + medianBlur(*input, result, MEDIAN_KERNEL_SIZE); + } + cust_stat("012_order_stats_filter_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + // 将原始输入和最后一次的结果传递给验证函数进行保存 + validate_median_blur_result(*input, result, file_suffix); +} + +int main() +{ + init_elf_dir(); + printf("开始 Median Blur (中值滤波)369 性能测试!\n\n"); + + // --- 测试灰度图 --- + printf("--- 开始测试灰度图 ---\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("灰度图加速前 (Median Blur)", "gray_default", true); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("灰度图加速后 (Median Blur)", "gray_ive", true); + cust_stat("012_order_stats_filter_demo"); + printf("\n--- 测试完成 ---\n\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/013_threshold_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/013_threshold_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/013_threshold_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/013_threshold_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/013_threshold_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a2f17e11b528d60b7eefc99ff5c849532413639 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/013_threshold_demo/main_for_cxx.cpp @@ -0,0 +1,241 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr int THRESHOLD_VALUE = 127; +constexpr int MAX_VALUE = 255; +constexpr int BENCH_ITERATIONS = 2000; +constexpr int GRAY_MIN = 0; +constexpr int TEXT_LINE_SPAN = 15; +constexpr int TEXT_LINE_STEP = 3; +constexpr int TEXT_PIXEL_STEP = 2; +constexpr int TEXT_GRAY_VALUE = 200; +constexpr double K_TEXT_Y_RATIO = 0.9; +constexpr double K_TEXT_X_START_RATIO = 0.1; +constexpr double K_TEXT_X_END_RATIO = 0.7; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +static void fill_gradient_background(uint8_t* data) +{ + for (int x = 0; x < IMAGE_WIDTH; ++x) { + uint8_t gray_value = static_cast((double)x / IMAGE_WIDTH * MAX_VALUE); + for (int y = 0; y < IMAGE_HEIGHT; ++y) { + data[y * IMAGE_WIDTH + x] = gray_value; + } + } +} + +static void draw_white_rectangle(uint8_t* data) +{ + const int rect_x1 = IMAGE_WIDTH * 0.1; + const int rect_y1 = IMAGE_HEIGHT * 0.1; + const int rect_x2 = IMAGE_WIDTH * 0.3; + const int rect_y2 = IMAGE_HEIGHT * 0.5; + + for (int y = rect_y1; y < rect_y2; ++y) { + for (int x = rect_x1; x < rect_x2; ++x) { + if (y < IMAGE_HEIGHT && x < IMAGE_WIDTH) { + data[y * IMAGE_WIDTH + x] = MAX_VALUE; + } + } + } +} + +static void draw_black_circle(uint8_t* data) +{ + const int center_x = IMAGE_WIDTH * 0.7; + const int center_y = IMAGE_HEIGHT * 0.3; + const int radius = IMAGE_HEIGHT * 0.15; + const int radius_sq = radius * radius; + + for (int y = center_y - radius; y < center_y + radius; ++y) { + for (int x = center_x - radius; x < center_x + radius; ++x) { + if (y < 0 || y >= IMAGE_HEIGHT || x < 0 || x >= IMAGE_WIDTH) { + continue; + } + + int dx = x - center_x; + int dy = y - center_y; + if (dx * dx + dy * dy > radius_sq) { + continue; + } + + data[y * IMAGE_WIDTH + x] = GRAY_MIN; + } + } +} + +static void draw_text_like_strokes(uint8_t* data) +{ + const int text_y = static_cast(IMAGE_HEIGHT * K_TEXT_Y_RATIO); + + for (int offset = 0; offset < TEXT_LINE_SPAN; offset += TEXT_LINE_STEP) { + for (int x = static_cast(IMAGE_WIDTH * K_TEXT_X_START_RATIO); + x < static_cast(IMAGE_WIDTH * K_TEXT_X_END_RATIO); + x += TEXT_PIXEL_STEP) { + if (text_y - offset >= 0 && text_y - offset < IMAGE_HEIGHT) { + data[(text_y - offset) * IMAGE_WIDTH + x] = TEXT_GRAY_VALUE; + } + } + } +} + +static void add_noise_patch(uint8_t* data) +{ + const int noise_x_start = IMAGE_WIDTH * 0.6; + const int noise_y_start = IMAGE_HEIGHT * 0.6; + const int noise_width = IMAGE_WIDTH * 0.3; + const int noise_height = IMAGE_HEIGHT * 0.3; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(GRAY_MIN, MAX_VALUE); + + for (int y = noise_y_start; y < noise_y_start + noise_height; ++y) { + for (int x = noise_x_start; x < noise_x_start + noise_width; ++x) { + if (y < IMAGE_HEIGHT && x < IMAGE_WIDTH) { + data[y * IMAGE_WIDTH + x] = static_cast(dis(gen)); + } + } + } +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +/** + * @brief 生成一个包含多种元素的、对比明显的结构化灰度图像。 + * @return 返回一个包含该图像的智能指针。 + */ +std::shared_ptr gen_structured_grayscale_image() +{ + auto image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + uint8_t* data = image->data; + + fill_gradient_background(data); + draw_white_rectangle(data); + draw_black_circle(data); + draw_text_like_strokes(data); + add_noise_patch(data); + + return image; +} + +bool validate_threshold_result(const Mat& original_img, const Mat& thresholded_img, const string& file_suffix) +{ + // 更新文件名以反映输入图像的类型 + string original_filename = g_elf_dir + "/structured_grayscale_input_" + file_suffix + ".png"; + string output_filename = g_elf_dir + "/binary_output_" + file_suffix + ".png"; + + bool save_original_success = imwrite(original_filename, original_img); + bool save_thresholded_success = imwrite(output_filename, thresholded_img); + if (save_original_success && save_thresholded_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将结构化灰度图保存为: " << original_filename << endl; + cout << "已将二值化结果图保存为: " << output_filename << endl; + cout << "原始图像尺寸: " << original_img.cols << "x" << original_img.rows << endl; + cout << "输出图像尺寸: " << thresholded_img.cols << "x" << thresholded_img.rows << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +void test_work(const char* hint, const string& file_suffix, int a = -1, int counter = BENCH_ITERATIONS) +{ + // 调用新的图像生成函数 + auto input = gen_structured_grayscale_image(); + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + threshold(*input, result, THRESHOLD_VALUE, MAX_VALUE, THRESH_BINARY); + } + cust_stat("013_threshold_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + validate_threshold_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 Threshold (图像二值化) 性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (Threshold)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (Threshold)", "ive"); + cust_stat("013_threshold_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/014_dma/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/014_dma/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/014_dma/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/014_dma/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/014_dma/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..694fbb8417beced9c1be82be4ef96b7476928fb4 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/014_dma/main_for_cxx.cpp @@ -0,0 +1,187 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; +using namespace std::chrono; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int IMAGE_WIDTH = 4096; +constexpr int IMAGE_HEIGHT = 4096; +constexpr int LINE_WIDTH = 2; +constexpr int BENCH_ITERATIONS = 1000; +constexpr int GRAY_MAX = 255; +constexpr int MID_GRAY = 128; +constexpr int GRID_STEP = 32; +constexpr double K_MICROSECONDS_PER_SECOND = 1000000.0; + +} // namespace + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成测试图像 (8UC1灰度格式) + */ +auto gen_structured_gray_image() -> std::shared_ptr +{ + // 创建一个灰度渐变图像 + auto grayImage = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 创建从左到右的渐变 + for (int y = 0; y < IMAGE_HEIGHT; y++) { + for (int x = 0; x < IMAGE_WIDTH; x++) { + grayImage->at(y, x) = static_cast((x * GRAY_MAX) / IMAGE_WIDTH); + } + } + + // 添加一些垂直线条增加纹理 + for (int x = 0; x < IMAGE_WIDTH; x += GRID_STEP) { + line(*grayImage, Point(x, 0), Point(x, IMAGE_HEIGHT), Scalar(GRAY_MAX), LINE_WIDTH); + } + + // 添加一些水平线条 + for (int y = 0; y < IMAGE_HEIGHT; y += GRID_STEP) { + line(*grayImage, Point(0, y), Point(IMAGE_WIDTH, y), Scalar(MID_GRAY), LINE_WIDTH); + } + + return grayImage; +} + +/** + * @brief 验证处理结果并保存图像 + */ +bool validate_result(const Mat& mat1, const Mat& mat2, double tolerance = 1e-6) +{ + // 检查矩阵尺寸是否相同 + if (mat1.size() != mat2.size()) { + cout << "矩阵尺寸不同: mat1=" << mat1.size() << ", mat2=" << mat2.size() << endl; + return false; + } + + // 检查矩阵类型是否相同 + if (mat1.type() != mat2.type()) { + cout << "矩阵类型不同: mat1=" << mat1.type() << ", mat2=" << mat2.type() << endl; + return false; + } + + // 比较矩阵内容 + Mat diff; + if (mat1.depth() == CV_32F || mat1.depth() == CV_64F) { + // 对于浮点矩阵,使用带容差的比较 + absdiff(mat1, mat2, diff); + Mat mask = diff > tolerance; + if (countNonZero(mask) > 0) { + cout << "矩阵内容不同: " << countNonZero(mask) << " 个像素超过容差 " << tolerance << endl; + return false; + } + } else { + // 对于整数矩阵,使用精确比较 + compare(mat1, mat2, diff, CMP_NE); + int different_pixels = countNonZero(diff); + if (different_pixels > 0) { + cout << "矩阵内容不同: " << different_pixels << " 个像素不匹配" << endl; + return false; + } + } + + cout << "矩阵验证通过: 两个矩阵完全相同" << endl; + return true; +} + +/** + * @brief 测试梯度幅度和角度计算功能 + */ +void test_dma_copy(const char* hint, + const string& implementation, + const string& file_suffix, + int counter = BENCH_ITERATIONS) +{ + // 生成测试图像 + auto src_gray = gen_structured_gray_image(); + + Mat dst(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 计时开始 + auto start = high_resolution_clock::now(); + + int c = 0; + while (++c <= counter) { + src_gray->copyTo(dst); + } + + // 计时结束 + auto end = high_resolution_clock::now(); + auto duration = duration_cast(end - start); + double seconds = duration.count() / K_MICROSECONDS_PER_SECOND; + cust_stat("014_dma", seconds); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, seconds); + + // 验证拷贝结果 + bool is_valid = validate_result(*src_gray, dst); + if (is_valid) { + cout << "数据拷贝验证成功!" << endl; + } else { + cout << "数据拷贝验证失败!" << endl; + } +} + +/** + * @brief 程序主入口 + */ +int main() +{ + printf("开始梯度幅度和角度计算性能测试!\n\n"); + // 测试OpenCV实现 + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_dma_copy("OpenCV实现", "opencv", "test1"); + printf("\n"); + // 测试IVE实现 + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_dma_copy("IVE实现", "ive", "test2"); + cust_stat("014_dma"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b2e0f75dfce624871e02e5ff0e38f7e39e4248c --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/015_threshold_s16_demo/main_for_cxx.cpp @@ -0,0 +1,184 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr double MIN_VAL = 0; +constexpr double MAX_VAL = 255; +constexpr int NORM_MIN = 0; +constexpr int NORM_MAX = 255; +constexpr int BENCH_ITERATIONS = 100; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +auto gen_structured_s16_image() +{ + auto s16Image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16S); + s16Image->setTo(cv::Scalar(MAX_VAL)); + + return s16Image; +} + +void printPixelValues(const cv::Mat& s16_input, const cv::Mat& u8_output) +{ + // 检查 s16_input 矩阵 + if (!s16_input.empty() && s16_input.rows > 0 && s16_input.cols > 0) { + // 获取 s16_input (0,0) 位置的像素值 + short s16_value = s16_input.at(0, 0); + cout << "s16_input pixel at (0,0): " << s16_value << endl; + } else { + cout << "s16_input matrix is empty or has no data" << endl; + } + + // 检查 u8_output 矩阵 + if (!u8_output.empty() && u8_output.rows > 0 && u8_output.cols > 0) { + // 获取 u8_output (0,0) 位置的像素值 + uchar u8_value = u8_output.at(0, 0); + std::cout << "u8_output pixel at (0,0): " << static_cast(u8_value) << std::endl; + } else { + std::cout << "u8_output matrix is empty or has no data" << std::endl; + } +} + +/** + * @brief 验证S16到U8转换的结果,并保存输入和输出图像。 + * @param s16_input 原始的S16格式输入图像。 + * @param u8_output 转换后生成的U8格式图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_conversion_result(const Mat& s16_input, const Mat& u8_output, const string& file_suffix) +{ + // S16图像不能直接保存为常见的PNG/JPG格式来正确显示负值。 + // 我们需要先将其归一化到0-255范围,生成一个“可视化版本”的灰度图来保存。 + Mat s16_viewable; + printPixelValues(s16_input, u8_output); + + normalize(s16_input, s16_viewable, NORM_MIN, NORM_MAX, NORM_MINMAX, CV_8U); + + string s16_filename = g_elf_dir + "/structured_s16_input_" + file_suffix + ".png"; + string u8_filename = g_elf_dir + "/converted_u8_output_" + file_suffix + ".png"; + + cout << "--- 结果已保存 ---" << endl; + bool save_s16_success = imwrite(s16_filename, s16_viewable); + bool save_u8_success = imwrite(u8_filename, u8_output); + if (save_s16_success && save_u8_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将S16输入图(可视化版)保存为: " << s16_filename << endl; + cout << "已将转换后的U8输出图保存为: " << u8_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief S16转U8性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + auto input = gen_structured_s16_image(); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + + while (++c <= counter) { + // --- 核心计算逻辑:S16转U8的完整流程 --- + cv::threshold_s16(*input, result, MIN_VAL, MAX_VAL); + // --- 核心计算逻辑结束 --- + } + cust_stat("015_threshold_s16_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + validate_conversion_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 S16 to U8 转换性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (S16toU8)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (S16toU8)", "ive"); + cust_stat("015_threshold_s16_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdff1b6b62e6ab5cae1aaea4146754e40674850b --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/016_threshold_u16_demo/main_for_cxx.cpp @@ -0,0 +1,180 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr double MIN_VAL = 2000; +constexpr double MAX_VAL = 5000; +constexpr int NORM_MIN = 0; +constexpr int NORM_MAX = 255; +constexpr int BENCH_ITERATIONS = 10; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +auto gen_structured_u16_image() +{ + auto u16Image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16U); + u16Image->setTo(cv::Scalar(MAX_VAL)); + + return u16Image; +} + +void printPixelValues(const cv::Mat& s16_input, const cv::Mat& u8_output) +{ + // 检查 s16_input 矩阵 + if (!s16_input.empty() && s16_input.rows > 0 && s16_input.cols > 0) { + // 获取 s16_input (0,0) 位置的像素值 + short s16_value = s16_input.at(0, 0); + cout << "s16_input pixel at (0,0): " << s16_value << endl; + } else { + cout << "s16_input matrix is empty or has no data" << endl; + } + + // 检查 u8_output 矩阵 + if (!u8_output.empty() && u8_output.rows > 0 && u8_output.cols > 0) { + // 获取 u8_output (0,0) 位置的像素值 + uchar u8_value = u8_output.at(0, 0); + std::cout << "u8_output pixel at (0,0): " << static_cast(u8_value) << std::endl; + } else { + std::cout << "u8_output matrix is empty or has no data" << std::endl; + } +} + +/** + * @brief 验证U16到U8转换的结果,并保存输入和输出图像。 + * @param u16_input 原始的U16格式输入图像。 + * @param u8_output 转换后生成的U8格式图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_conversion_result(const Mat& u16_input, const Mat& u8_output, const string& file_suffix) +{ + // U16图像需要先归一化到0-255范围,才能生成一个便于肉眼观察的“预览图”来保存。 + Mat u16_viewable; + printPixelValues(u16_input, u8_output); + normalize(u16_input, u16_viewable, NORM_MIN, NORM_MAX, NORM_MINMAX, CV_8U); + + string u16_filename = g_elf_dir + "/structured_u16_input_" + file_suffix + ".png"; + string u8_filename = g_elf_dir + "/converted_u8_output_" + file_suffix + ".png"; + + bool save_u16_success = imwrite(u16_filename, u16_viewable); + bool save_u8_success = imwrite(u8_filename, u8_output); + if (save_u16_success && save_u8_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将U16输入图(可视化版)保存为: " << u16_filename << endl; + cout << "已将转换后的U8输出图保存为: " << u8_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief U16转U8性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + auto input = gen_structured_u16_image(); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑:U16转U8的完整流程 --- + cv::threshold_u16(*input, result, MIN_VAL, MAX_VAL); + // --- 核心计算逻辑结束 --- + } + cust_stat("016_threshold_u16_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + validate_conversion_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 U16 to U8 转换性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (U16toU8)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (U16toU8)", "ive"); + cust_stat("016_threshold_u16_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..929f91739d60cc52621e96167358baba9eafdf67 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/017_16bit_to_8bit_demo/main_for_cxx.cpp @@ -0,0 +1,171 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr double SCALE_FACTOR = 255.0 / 65535.0; +constexpr int K_U16_MAX = 65535; +constexpr int K_U16_MID = 32767; +constexpr int K_U16_MIN = 0; +constexpr int BENCH_ITERATIONS = 100; +constexpr int IMAGE_QUARTER_DIV = 4; +constexpr int IMAGE_HALF_DIV = 2; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成一个结构化的、便于观察的U16图像。 + * 图像包含一个完整的0-65535渐变和几个关键值色块。 + * @return 返回一个包含该U16图像的智能指针。 + */ +auto gen_structured_u16_image() -> std::shared_ptr +{ + auto u16Image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16UC1); + + // 1. 创建一个从0到65535的水平渐变 + for (int x = 0; x < u16Image->cols; ++x) { + ushort value = static_cast((double) x / (u16Image->cols - 1) * K_U16_MAX); + u16Image->col(x).setTo(Scalar(value)); + } + + // 2. 在顶部绘制几个关键值的纯色块,用于精确验证 + // 纯黑 (0) + (*u16Image)(Rect(0, 0, IMAGE_WIDTH / IMAGE_QUARTER_DIV, + IMAGE_HEIGHT / IMAGE_QUARTER_DIV)).setTo(Scalar(K_U16_MIN)); + // 中灰色 (32767) + (*u16Image)(Rect(IMAGE_WIDTH / IMAGE_QUARTER_DIV, 0, IMAGE_WIDTH / IMAGE_QUARTER_DIV, + IMAGE_HEIGHT / IMAGE_QUARTER_DIV)).setTo(Scalar(K_U16_MID)); + // 纯白 (65535) + (*u16Image)(Rect(IMAGE_WIDTH / IMAGE_HALF_DIV, 0, IMAGE_WIDTH / IMAGE_QUARTER_DIV, + IMAGE_HEIGHT / IMAGE_QUARTER_DIV)).setTo(Scalar(K_U16_MAX)); + + return u16Image; +} + +/** + * @brief 验证U16到U8转换的结果,并保存输入和输出图像。 + * @param u16_input 原始的U16格式输入图像。 + * @param u8_output 转换后生成的U8格式图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_conversion_result(const Mat& u8_output, const string& file_suffix) +{ + string u8_filename = g_elf_dir + "/linear_converted_u8_output_" + file_suffix + ".png"; + + bool save_u8_success = imwrite(u8_filename, u8_output); + if (save_u8_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将转换后的U8输出图保存为: " << u8_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief U16转U8线性转换性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + auto input = gen_structured_u16_image(); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑:U16转U8线性缩放 --- + input->convertTo(result, CV_8U, SCALE_FACTOR); + } + cust_stat("017_16bit_to_8bit_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + validate_conversion_result(result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 U16 to U8 线性转换性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (U16toU8 Linear)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (U16toU8 Linear)", "ive"); + cust_stat("017_16bit_to_8bit_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/018_integ_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/018_integ_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/018_integ_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/018_integ_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/018_integ_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a05527b164e24bb9ab4a2d184559353809174bbe --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/018_integ_demo/main_for_cxx.cpp @@ -0,0 +1,271 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1280; +constexpr int IMAGE_HEIGHT = 720; +constexpr int GRAY_MAX = 255; +constexpr int GRAY_MIN = 0; +constexpr int NORM_MIN = 0; +constexpr int NORM_MAX = 255; +constexpr int BENCH_ITERATIONS = 50; +constexpr int INTEGRAL_VERIFY_COUNT = 50; +constexpr int INTEGRAL_DUMP_SIZE = 50; +constexpr int RAND_SEED = 0; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} + +bool verifyIntegral(const cv::Mat& image, const cv::Mat& integral); +void saveIntegralToText(const cv::Mat& integral, const std::string& filename, int max_rows, int max_cols); + +/** + * @brief 生成一个结构化的、便于观察的灰度图像。 + * @return 返回一个包含该灰度图像的智能指针。 + */ +auto gen_structured_grayscale_image() -> std::shared_ptr +{ + auto image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 1. 左侧1/3为纯黑 + (*image)(Rect(0, 0, IMAGE_WIDTH / 3, IMAGE_HEIGHT)).setTo(Scalar(GRAY_MIN)); + + // 2. 右侧1/3为纯白 + (*image)(Rect(IMAGE_WIDTH * 2 / 3, 0, IMAGE_WIDTH / 3, IMAGE_HEIGHT)) + .setTo(Scalar(GRAY_MAX)); /* 2: right-third region starts at two-thirds width */ + + // 3. 中间1/3为从黑到白的垂直渐变 + Mat middle_part = (*image)(Rect(IMAGE_WIDTH / 3, 0, IMAGE_WIDTH / 3, IMAGE_HEIGHT)); + for (int y = 0; y < middle_part.rows; ++y) { + uchar value = static_cast((double) y / (middle_part.rows - 1) * GRAY_MAX); + middle_part.row(y).setTo(Scalar(value)); + } + + return image; +} + +/** + * @brief 验证积分图的计算结果,并保存相关的可视化图和数据文件。 + * @param original_img 原始的输入灰度图。 + * @param integral_img 计算得到的积分图 (CV_32S)。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 如果所有验证都通过,返回true。 + */ +bool validate_integral_result(const Mat& original_img, const Mat& integral_img, const string& file_suffix) +{ + // 1. 保存原始输入图 + string input_filename = g_elf_dir + "/structured_input_" + file_suffix + ".png"; + imwrite(input_filename, original_img); + cout << "已将结构化输入图保存为: " << input_filename << endl; + + // 2. 创建并保存积分图的可视化版本 + Mat integral_visual; + normalize(integral_img, integral_visual, NORM_MIN, NORM_MAX, NORM_MINMAX, CV_8U); + string visual_filename = g_elf_dir + "/integral_visual_" + file_suffix + ".png"; + imwrite(visual_filename, integral_img); + cout << "已将积分图(可视化版)保存为: " << visual_filename << endl; + + // 3. 将积分图的局部数据保存到文本文件,便于精确检查 + string text_filename = g_elf_dir + "/integral_partial_" + file_suffix + ".txt"; + saveIntegralToText(integral_img, text_filename, INTEGRAL_DUMP_SIZE, INTEGRAL_DUMP_SIZE); // 保存左上角50x50的数据 + // 4. 对积分图的正确性进行严格的随机抽样验证 + cout << "\n正在验证积分图正确性..." << endl; + if (verifyIntegral(original_img, integral_img)) { + cout << "✅ 积分图验证通过!" << endl; + return true; + } else { + cerr << "❌ 积分图验证失败!" << endl; + return false; + } +} + +/** + * @brief 积分图计算性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + // 初始化随机数生成器,确保每次验证的随机区域一致 + srand(RAND_SEED); + auto input = gen_structured_grayscale_image(); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_32S); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑:计算积分图 --- + integral(*input, result, CV_32S); + } + cust_stat("018_integ_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + validate_integral_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 Integral Image (积分图) 计算性能测试!\n\n"); + + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (Integral)", "default"); + + printf("\n"); + + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (Integral)", "ive"); + cust_stat("018_integ_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} + +bool verifyIntegral(const cv::Mat& image, const cv::Mat& integral) +{ + if (integral.type() != CV_32S) { + std::cerr << "错误: 积分图不是 CV_32S 类型!" << std::endl; + return false; + } + + // 检查尺寸是否匹配(现在积分图与原始图像尺寸相同) + if (integral.rows != image.rows || integral.cols != image.cols) { + std::cerr << "尺寸不匹配! 图像尺寸: " << image.rows << "x" << image.cols << ", 积分图尺寸: " << integral.rows + << "x" << integral.cols << std::endl; + return false; + } + + const int test_count = INTEGRAL_VERIFY_COUNT; + int errors = 0; + + for (int i = 0; i < test_count; i++) { + int x1 = rand() % image.cols; + int y1 = rand() % image.rows; + int width = rand() % (image.cols - x1) + 1; + int height = rand() % (image.rows - y1) + 1; + + int x2 = x1 + width - 1; + int y2 = y1 + height - 1; + + int a = (x1 > 0 && y1 > 0) ? integral.at(y1 - 1, x1 - 1) : 0; + int b = (y1 > 0) ? integral.at(y1 - 1, x2) : 0; + int c = (x1 > 0) ? integral.at(y2, x1 - 1) : 0; + int d = integral.at(y2, x2); + + int integral_sum = d - b - c + a; + + double direct_sum = cv::sum(image(cv::Rect(x1, y1, width, height)))[0]; + if (std::abs(static_cast(integral_sum) - direct_sum) > 1.0) { + errors++; + std::cerr << "区域 (" << x1 << "," << y1 << ") - (" << x2 << "," << y2 << ") 不匹配: 积分图=" << integral_sum + << ", 直接计算=" << direct_sum << std::endl; + } + } + + if (errors > 0) { + std::cerr << "发现 " << errors << "/" << test_count << " 个区域和不匹配!" << std::endl; + return false; + } + + std::cout << "所有 " << test_count << " 个测试区域都匹配!" << std::endl; + return true; +} + +/** + * @brief 将积分图的数值数据保存到文本文件,便于调试和检查。 + */ +void saveIntegralToText(const cv::Mat& integral, const std::string& filename, int max_rows = 0, int max_cols = 0) +{ + ofstream out_file(filename); + if (!out_file.is_open()) { + cerr << "错误: 无法打开文件 " << filename << " 进行写入!" << endl; + return; + } + + out_file << right << fixed; + int rows = (max_rows > 0 && max_rows < integral.rows) ? max_rows : integral.rows; + int cols = (max_cols > 0 && max_cols < integral.cols) ? max_cols : integral.cols; + + double min_val; + double max_val; + minMaxLoc(integral, &min_val, &max_val); + int width = static_cast(std::log10(max_val)) + 4; + + for (int y = 0; y < rows; y++) { + for (int x = 0; x < cols; x++) { + out_file << setw(width) << integral.at(y, x); + } + out_file << endl; + } + out_file.close(); + cout << "已将部分积分图数据保存到 " << filename << endl; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/019_hist_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/019_hist_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/019_hist_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/019_hist_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/019_hist_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a7dd70a412625537c22974b6fa02a15a4dbbf23 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/019_hist_demo/main_for_cxx.cpp @@ -0,0 +1,207 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr int HIST_SIZE = 256; +constexpr int GRAY_MAX = 255; +constexpr int GRAY_MIN = 0; +constexpr int MID_GRAY = 128; +constexpr int HIST_RANGE_MAX = 256; +constexpr int HIST_VISUAL_WIDTH = 512; +constexpr int HIST_VISUAL_HEIGHT = 400; +constexpr int HIST_LINE_WIDTH = 2; +constexpr int HIST_BG_GRAY = 20; +constexpr int HIST_LINE_GRAY = 200; +constexpr int BENCH_ITERATIONS = 100; +constexpr int HIST_RESULT_COLS = 1024; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成一个结构化的、便于观察直方图的灰度图像。 + * @return 返回一个包含该灰度图像的智能指针。 + */ +auto gen_structured_grayscale_image() -> std::shared_ptr +{ + auto image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + int quarter_width = IMAGE_WIDTH / 4; + + // 1. 左侧1/4为纯黑 (0) + (*image)(Rect(0, 0, quarter_width, IMAGE_HEIGHT)).setTo(Scalar(GRAY_MIN)); + + // 2. 中左侧1/4为中灰 (128) + (*image)(Rect(quarter_width, 0, quarter_width, IMAGE_HEIGHT)).setTo(Scalar(MID_GRAY)); + + // 3. 中右侧1/4为纯白 (255) + (*image)(Rect(quarter_width * 2, 0, quarter_width, IMAGE_HEIGHT)) + .setTo(Scalar(GRAY_MAX)); /* 2: third quarter starts after two quarter blocks */ + + // 4. 右侧1/4为从黑到白的水平渐变 + Mat gradient_roi = (*image)(Rect(quarter_width * 3, 0, IMAGE_WIDTH - quarter_width * 3, IMAGE_HEIGHT)); + for (int x = 0; x < gradient_roi.cols; ++x) { + uchar value = static_cast((double) x / (gradient_roi.cols - 1) * GRAY_MAX); + gradient_roi.col(x).setTo(Scalar(value)); + } + + return image; +} + +/** + * @brief 验证直方图的计算结果,并保存相关的可视化图和数据文件。 + * @param original_img 原始的输入灰度图。 + * @param hist 计算得到的直方图数据 (CV_32F)。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_histogram_result(const Mat& original_img, const Mat& hist, const string& file_suffix) +{ + // 1. 保存原始输入图 + string input_filename = g_elf_dir + "/structured_input_" + file_suffix + ".png"; + imwrite(input_filename, original_img); + cout << "已将结构化输入图保存为: " << input_filename << endl; + + string csv_filename = g_elf_dir + "/histogram_data_" + file_suffix + ".csv"; + ofstream hist_file(csv_filename); + if (hist_file.is_open()) { + hist_file << "Bin,Value\n"; + for (int i = 0; i < HIST_SIZE; i++) { + hist_file << i << "," << hist.at(i) << "\n"; + } + hist_file.close(); + cout << "已将直方图数据保存到: " << csv_filename << endl; + } + + const int hist_width = HIST_VISUAL_WIDTH; + const int hist_height = HIST_VISUAL_HEIGHT; + const int bin_width = cvRound((double) hist_width / HIST_SIZE); + Mat hist_image(hist_height, hist_width, CV_8UC3, Scalar(HIST_BG_GRAY, HIST_BG_GRAY, HIST_BG_GRAY)); + + Mat normalized_hist; + normalize(hist, normalized_hist, GRAY_MIN, hist_image.rows, NORM_MINMAX); + + for (int i = 1; i < HIST_SIZE; i++) { + line(hist_image, + Point(bin_width * (i - 1), hist_height - cvRound(normalized_hist.at(i - 1))), + Point(bin_width * i, hist_height - cvRound(normalized_hist.at(i))), + Scalar(HIST_LINE_GRAY, HIST_LINE_GRAY, HIST_LINE_GRAY), + HIST_LINE_WIDTH); + } + + string hist_img_filename = "histogram_visual_" + file_suffix + ".png"; + imwrite(hist_img_filename, hist_image); + cout << "已将直方图(可视化版)保存为: " << hist_img_filename << endl; + + return true; +} + +/** + * @brief 直方图计算性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + auto input = gen_structured_grayscale_image(); + + Mat result(1, HIST_RESULT_COLS, CV_8UC1); + float range[] = {GRAY_MIN, static_cast(HIST_RANGE_MAX)}; + const float* hist_range = {range}; + + spdlog::stopwatch sw; + int c = 0; + auto mask = Mat(); + while (++c <= counter) { + // --- 核心计算逻辑:计算直方图 --- + calcHist(&(*input), 1, 0, mask, result, 1, &HIST_SIZE, &hist_range); + } + cust_stat("019_hist_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + validate_histogram_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 Histogram (直方图) 计算性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (Histogram)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (Histogram)", "ive"); + cust_stat("019_hist_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/020_map_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/020_map_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/020_map_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/020_map_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/020_map_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..137dcd65a05ff38a43fd22e83a35fdc2cf9b12e8 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/020_map_demo/main_for_cxx.cpp @@ -0,0 +1,179 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 1920; +constexpr int IMAGE_HEIGHT = 1080; +constexpr int LUT_VALUE_MID = 100; +constexpr int LUT_VALUE_HIGH = 255; +constexpr int LUT_INPUT_THRESHOLD_HIGH = 200; +constexpr int LUT_TABLE_SIZE = 256; +constexpr int GRAY_MAX = 255; +constexpr int BENCH_ITERATIONS = 1000; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成一个从黑到白的平滑渐变灰度图,用于测试LUT。 + * @return 返回一个包含该灰度图像的智能指针。 + */ +auto gen_structured_grayscale_image() -> std::shared_ptr +{ + auto image = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 创建一个从0到255的水平渐变 + for (int x = 0; x < image->cols; ++x) { + uchar value = static_cast((double) x / (image->cols - 1) * GRAY_MAX); + image->col(x).setTo(Scalar(value)); + } + return image; +} + +/** + * @brief 根据指定的规则初始化并创建一个OpenCV格式的查找表。 + * @return 返回一个 CV_8UC1 类型的 Mat 作为查找表。 + */ +auto create_lookup_table() -> cv::Mat +{ + Mat lut(1, LUT_TABLE_SIZE, CV_8UC1); + for (int i = 0; i < LUT_TABLE_SIZE; i++) { + if (i <= LUT_INPUT_THRESHOLD_HIGH) { + lut.at(i) = LUT_VALUE_MID; + } else { + lut.at(i) = LUT_VALUE_HIGH; + } + } + return lut; +} + +/** + * @brief 验证LUT操作的结果,并保存输入和输出图像。 + * @param original_img 原始的输入灰度图。 + * @param result_img 经过LUT处理后的结果图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_lut_result(const Mat& original_img, const Mat& result_img, const string& file_suffix) +{ + string input_filename = g_elf_dir + "/structured_input_" + file_suffix + ".png"; + string output_filename = g_elf_dir + "/lut_output_" + file_suffix + ".png"; + + bool save_input_success = imwrite(input_filename, original_img); + bool save_output_success = imwrite(output_filename, result_img); + if (save_input_success && save_output_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将渐变输入图保存为: " << input_filename << endl; + cout << "已将LUT转换结果图保存为: " << output_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief LUT性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + auto input = gen_structured_grayscale_image(); + auto lut = create_lookup_table(); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑:应用查找表 --- + LUT(*input, lut, result); + } + cust_stat("020_map_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + validate_lut_result(*input, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 LUT (查找表) 计算性能测试!\n\n"); + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (LUT)", "default"); + printf("\n"); + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (LUT)", "ive"); + cust_stat("020_map_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/021_mag_and_ang/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/021_mag_and_ang/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/021_mag_and_ang/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/021_mag_and_ang/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/021_mag_and_ang/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..661dad2b3db47a6789c7c52e75445c655b4ca7af --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/021_mag_and_ang/main_for_cxx.cpp @@ -0,0 +1,186 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; +using namespace std::chrono; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 512; +constexpr int IMAGE_HEIGHT = 512; +constexpr int LINE_WIDTH = 2; +constexpr int GRAY_MAX = 255; +constexpr int MID_GRAY = 128; +constexpr int GRID_STEP = 32; +constexpr int BENCH_ITERATIONS = 10; +constexpr double K_MICROSECONDS_PER_SECOND = 1000000.0; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成测试图像 (8UC1灰度格式) + */ +auto gen_structured_gray_image() -> std::shared_ptr +{ + // 创建一个灰度渐变图像 + auto grayImage = std::make_shared(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 创建从左到右的渐变 + for (int y = 0; y < IMAGE_HEIGHT; y++) { + for (int x = 0; x < IMAGE_WIDTH; x++) { + grayImage->at(y, x) = static_cast((x * GRAY_MAX) / IMAGE_WIDTH); + } + } + + // 添加一些垂直线条增加纹理 + for (int x = 0; x < IMAGE_WIDTH; x += GRID_STEP) { + line(*grayImage, Point(x, 0), Point(x, IMAGE_HEIGHT), Scalar(GRAY_MAX), LINE_WIDTH); + } + + // 添加一些水平线条 + for (int y = 0; y < IMAGE_HEIGHT; y += GRID_STEP) { + line(*grayImage, Point(0, y), Point(IMAGE_WIDTH, y), Scalar(MID_GRAY), LINE_WIDTH); + } + + return grayImage; +} + +/** + * @brief 验证处理结果并保存图像 + */ +bool validate_result( + const Mat& src, const Mat& dst_mag, const Mat& dst_ang, const string& implementation, const string& file_suffix) +{ + string src_filename = g_elf_dir + "/src_image_" + file_suffix + ".png"; + string dst_mag_filename = g_elf_dir + "/dst_mag_" + implementation + "_" + file_suffix + ".png"; + string dst_ang_filename = g_elf_dir + "/dst_ang_" + implementation + "_" + file_suffix + ".png"; + + bool save1_success = imwrite(src_filename, src); + bool save2_success = imwrite(dst_mag_filename, dst_mag); + bool save3_success = imwrite(dst_ang_filename, dst_ang); + if (save1_success && save2_success && save3_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "源图像保存为: " << src_filename << endl; + cout << implementation << " 幅度结果保存为: " << dst_mag_filename << endl; + cout << implementation << " 角度结果保存为: " << dst_ang_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief 测试梯度幅度和角度计算功能 + */ +void test_mag_and_ang(const char* hint, + const string& implementation, + const string& file_suffix, + int counter = BENCH_ITERATIONS) +{ + // 生成测试图像 + auto src_gray = gen_structured_gray_image(); + + Mat mag_result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_16UC1); + Mat ang_result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + // 计时开始 + auto start = high_resolution_clock::now(); + + int c = 0; + while (++c <= counter) { + cv::mag_and_ang(*src_gray, mag_result, ang_result); + } + + // 计时结束 + auto end = high_resolution_clock::now(); + auto duration = duration_cast(end - start); + double seconds = duration.count() / K_MICROSECONDS_PER_SECOND; + cust_stat("021_mag_and_ang", seconds); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, seconds); + + validate_result(*src_gray, mag_result, ang_result, implementation, file_suffix); +} + +/** + * @brief 程序主入口 + */ +int main() +{ + init_elf_dir(); + printf("开始梯度幅度和角度计算性能测试!\n\n"); + // 测试OpenCV实现 + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_mag_and_ang("OpenCV实现", "opencv", "test1"); + printf("\n"); + // 测试IVE实现 + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_mag_and_ang("IVE实现", "ive", "test2"); + cust_stat("021_mag_and_ang"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/022_add_demo/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/022_add_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5313243e8e64cbb53c2bb3228f0458e03f78e679 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/022_add_demo/CMakeLists.txt @@ -0,0 +1,15 @@ +# 1.根据所在目录名称自动生成子工程的名称 +get_filename_component(sub_project_name "${CMAKE_CURRENT_SOURCE_DIR}" NAME) +# 2.对子工程进行命名 +project(${sub_project_name}) +# 3.添加调试标志 +set(CMAKE_BUILD_TYPE Debug) +# 4.向子工程增加编译需要生成的执行体(为了区别各个演示程序,执行体使用子工程名来标识) +add_executable(${sub_project_name} + main_for_cxx.cpp +) +# 5.输出的可执行文件采用统一的名称elf +set_target_properties(${sub_project_name} PROPERTIES OUTPUT_NAME "elf") +# 6.安装执行体到子工程标识的子目录 +install(TARGETS ${sub_project_name} RUNTIME DESTINATION ${sub_project_name} ) + \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/022_add_demo/main_for_cxx.cpp b/vendor/zsks/demo/opencv_ive/022_add_demo/main_for_cxx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75d163e7ce4b2d601b5efc8eb56cde5f72a61ba1 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/022_add_demo/main_for_cxx.cpp @@ -0,0 +1,180 @@ +/* + * Created by hf on 2025/6/5. + * Copyright (c) 2025 Zhongshan Kuangshi Microelectronics Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Modifications Author: yaohongtao (yht@cust.edu.cn) + */ + +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +namespace { + +enum class ive_accel_mode : int { + DISABLED = -1, + ENABLED = 1, +}; + +constexpr int PROC_PATH_BUF_SIZE = 4096; +constexpr int IMAGE_WIDTH = 512; +constexpr int IMAGE_HEIGHT = 512; +constexpr double ALPHA = 1; +constexpr double BETA = 1; +constexpr double GAMMA = 0.0; +constexpr int GRAY_MIN = 0; +constexpr int GRADIENT_MAX = 127; +constexpr int BENCH_ITERATIONS = 100; + +} // namespace + +/** 可执行文件所在目录(不含末尾斜杠),供资源路径拼接等复用 */ +std::string g_elf_dir; + +static void init_elf_dir() +{ + char buf[PROC_PATH_BUF_SIZE]; + ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (n < 0) { + g_elf_dir = "."; + return; + } + buf[n] = '\0'; + std::string path(buf); + const auto pos = path.find_last_of('/'); + g_elf_dir = (pos == std::string::npos) ? "." : path.substr(0, pos); +} + +void cust_stat(const char* title, double t = 0) +{ + static int counter = 0; + static double times[2] = {0, 0}; /* 2: before and after benchmark elapsed time */ + if (t > 0) { + times[counter++] = t; + return; + } + printf("\n"); + double before = times[0]; + double after = times[1]; + double effect = before / after; + printf("%s,加速前,%f,加速后,%f,加速比,%f\n", title, before, after, effect); + printf("\n"); +} +/** + * @brief 生成两张结构化的、便于观察的彩色渐变图像。 + * @param image1 用于存储垂直红色渐变图的Mat对象。 + * @param image2 用于存储水平绿色渐变图的Mat对象。 + */ +void gen_structured_images(Mat& image1, Mat& image2) +{ + image1.create(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); // 单通道 + image2.create(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); // 单通道 + image1.setTo(GRAY_MIN); + image2.setTo(GRAY_MIN); + + // 1. 纵向红色渐变 → 现在只是 0~127 的灰度渐变 + for (int y = 0; y < image1.rows; ++y) { + uchar v = static_cast(y * GRADIENT_MAX / (image1.rows - 1)); + image1.row(y).setTo(v); + } + + // 2. 横向绿色渐变 → 同样变成 0~127 的灰度渐变 + for (int x = 0; x < image2.cols; ++x) { + uchar v = static_cast(x * GRADIENT_MAX / (image2.cols - 1)); + image2.col(x).setTo(v); + } +} + +/** + * @brief 验证addWeighted操作的结果,并保存所有输入和输出图像。 + * @param input1 原始输入图像1。 + * @param input2 原始输入图像2。 + * @param result 加权和处理后的结果图像。 + * @param file_suffix 用于生成唯一文件名的后缀字符串。 + * @return 操作成功返回true。 + */ +bool validate_addWeighted_result(const Mat& input1, const Mat& input2, const Mat& result, const string& file_suffix) +{ + string input1_filename = g_elf_dir + "/input_image1_" + file_suffix + ".png"; + string input2_filename = g_elf_dir + "/input_image2_" + file_suffix + ".png"; + string output_filename = g_elf_dir + "/addWeighted_output_" + file_suffix + ".png"; + + bool save1_success = imwrite(input1_filename, input1); + bool save2_success = imwrite(input2_filename, input2); + bool save_output_success = imwrite(output_filename, result); + if (save1_success && save2_success && save_output_success) { + cout << "--- 结果已保存 ---" << endl; + cout << "已将输入图1保存为: " << input1_filename << endl; + cout << "已将输入图2保存为: " << input2_filename << endl; + cout << "已将加权和结果图保存为: " << output_filename << endl; + } else { + cerr << "错误: 图像保存失败!" << endl; + return false; + } + + return true; +} + +/** + * @brief addWeighted性能测试的核心函数。 + * @param hint 用于在日志中标识当前测试的描述性字符串。 + * @param file_suffix 传递给验证函数的文件后缀。 + * @param counter 核心算法的执行次数。 + */ +void test_work(const char* hint, const string& file_suffix, int counter = BENCH_ITERATIONS) +{ + // 使用智能指针管理内存 + auto input1 = std::make_shared(); + auto input2 = std::make_shared(); + gen_structured_images(*input1, *input2); + + Mat result(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1); + + spdlog::stopwatch sw; + int c = 0; + while (++c <= counter) { + // --- 核心计算逻辑:图像加权和 --- + addWeighted(*input1, ALPHA, *input2, BETA, GAMMA, result); + } + cust_stat("022_add_demo", sw.elapsed().count()); + CUST_LOGGER_CRITICAL("{},{}次耗时{}秒", hint, counter, sw.elapsed().count()); + + validate_addWeighted_result(*input1, *input2, result, file_suffix); +} + +/** + * @brief 程序主入口,负责调度不同的测试任务。 + */ +int main() +{ + init_elf_dir(); + printf("开始 addWeighted (图像加权和) 性能测试!\n\n"); + + ::cust::enable(static_cast(ive_accel_mode::DISABLED)); + test_work("加速前的opencv默认实现 (addWeighted)", "default"); + + printf("\n"); + + ::cust::enable(static_cast(ive_accel_mode::ENABLED)); + test_work("加速后的ive实现 (addWeighted)", "ive"); + cust_stat("022_add_demo"); + printf("\n--- 测试完成 ---\n"); + + return 0; +} \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/CMakeLists.txt b/vendor/zsks/demo/opencv_ive/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..514ce9d9d95b2c4552a646449f9addf7009e72c7 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/CMakeLists.txt @@ -0,0 +1,87 @@ +# 声明cmake解释器的最低版本 +cmake_minimum_required(VERSION 3.16) + +# set(CMAKE_CXX_FLAGS "-static") + +# 添加调试标志 +set(CMAKE_BUILD_TYPE Debug) + +project(demos_for_opencv_operator) + +set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/out/$ENV{CUST_BUILD_VARIANT}") + +################################################################################ +# 优化后的OpenCV库 - 直接链接,不依赖cmake配置文件 +get_filename_component(PROJECT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../.." ABSOLUTE) +set(OpenCV_ROOT_DIR "${PROJECT_ROOT_DIR}/opensource/opencv/$ENV{CUST_BUILD_VARIANT}") +set(MPP_ROOT_DIR "${PROJECT_ROOT_DIR}/../platform/ss928v100_$ENV{CUST_BUILD_VARIANT}/smp/a55_linux/mpp/out/lib") + +# 设置 RPATH,确保链接时和运行时能找到依赖库 +set(CMAKE_BUILD_RPATH "${MPP_ROOT_DIR}:${MPP_ROOT_DIR}/svp_npu:${OpenCV_ROOT_DIR}/lib") +set(CMAKE_INSTALL_RPATH "${MPP_ROOT_DIR}:${MPP_ROOT_DIR}/svp_npu:${OpenCV_ROOT_DIR}/lib") +set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE) + +# OpenCV头文件路径 +set(OpenCV_INCLUDE_DIRS "${OpenCV_ROOT_DIR}/include/opencv4") + +# 库目录 +link_directories( + "${OpenCV_ROOT_DIR}/lib" + "${MPP_ROOT_DIR}" + "${MPP_ROOT_DIR}/svp_npu" + "$ENV{dir_for_install_opencv_on_cloud}/lib" +) + +# 需要链接的MPP库 +set(MPP_LIBS + ss_mpi ss_ae ss_isp ot_isp ss_awb ss_dehaze ss_extend_stats ss_drc ss_ldci ss_crb ss_bnr ss_calcflicker ss_ir_auto ss_acs + sns_hy_s0603 sns_os08a20 sns_imx347_slave sns_os04a10 sns_sc450ai sns_sc450ai_2l + ss_voice_engine ss_upvqe ss_dnvqe aac_comm aac_enc aac_dec aac_sbr_enc aac_sbr_dec + vqe_res vqe_record vqe_hpf vqe_anr vqe_aec vqe_agc vqe_eq vqe_talkv2 + ss_hdmi ss_dpu_match ss_dpu_rect ss_mau ss_ive ss_pqp securec + svp_acl + protobuf-c dl + ot_osal ot_base ot_sys ot_chnl ot_rgn ot_vpp ot_vo ot_vgs ot_vpss ot_vdec ot_h265e ot_h264e ot_jpege ot_venc ot_vedu ot_vi ot_mpi_isp ot_rc ot_jpegd ot_vfmw ot_gdc ot_dis ot_irq ot_sensor_i2c ot_sensor_spi ot_pwm ot_piris ot_aio ot_ai ot_ao ot_aenc ot_adec ot_acodec +) + +# 需要链接的OpenCV库 +set(OpenCV_LIBS + opencv_gapi + opencv_highgui + opencv_ml + opencv_objdetect + opencv_photo + opencv_stitching + opencv_video + opencv_videoio + opencv_imgcodecs + opencv_dnn + opencv_calib3d + opencv_features2d + opencv_flann + opencv_imgproc + opencv_core +) + +# 头文件到哪里去找 +include_directories( + "${OpenCV_INCLUDE_DIRS}" + "$ENV{dir_for_log_lib}" +) + +link_libraries("${OpenCV_LIBS}" "${MPP_LIBS}") + +# 自动添加所有以数字开头的子目录(须为目录且含 CMakeLists.txt) +file(GLOB _opencv_ive_demo_dirs RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "[0-9]*") +list(SORT _opencv_ive_demo_dirs) +foreach(_d IN LISTS _opencv_ive_demo_dirs) + if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_d}" + AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_d}/CMakeLists.txt") + add_subdirectory("${_d}") + endif() +endforeach() + +install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/cust_stat.sh" + DESTINATION . +) + diff --git a/vendor/zsks/demo/opencv_ive/Makefile b/vendor/zsks/demo/opencv_ive/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..44ce901229b72e23c9a12ffb385c77201357ef45 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/Makefile @@ -0,0 +1,31 @@ +.PHONY: gcc clang + +export dir_for_log_lib?= $(PWD)/../../../opensource/log_lib +dir_for_opencv?= $(PWD)/../../../opensource/opencv +clear_gcc: + @echo "clear_gcc" + @rm -rfd ./build/gcc + @rm -rfd ./out/gcc + +gcc: clear_gcc + @mkdir -pv ./build/gcc + @mkdir -pv ./out/gcc + cd ./build/gcc \ + && export CUST_BUILD_VARIANT=gcc \ + && cmake $(realpath .) -D CMAKE_TOOLCHAIN_FILE=$(realpath ./gcc.cmake) \ + && cmake --build . \ + && cmake --install . + +clear_clang: + @echo "clear_clang" + @rm -rfd ./build/clang + @rm -rfd ./out/clang + +clang: clear_clang + @mkdir -pv ./build/clang + @mkdir -pv ./out/clang + cd ./build/clang \ + && export CUST_BUILD_VARIANT=clang \ + && cmake $(realpath .) -D CMAKE_TOOLCHAIN_FILE=$(realpath ./clang.cmake) \ + && cmake --build . \ + && cmake --install . diff --git a/vendor/zsks/demo/opencv_ive/README.md b/vendor/zsks/demo/opencv_ive/README.md old mode 100755 new mode 100644 index 332bc520d25f06bd214370ac569b78541ea876ee..ea1c32ba375a567ce195205205be9370468e8758 --- a/vendor/zsks/demo/opencv_ive/README.md +++ b/vendor/zsks/demo/opencv_ive/README.md @@ -1,54 +1,80 @@ -## 2.6、opencv_ive算子案例指导 +## 3.6、opencv_ive算子案例指导 -### 2.6.1、opencv_ive 算子案例介绍 +### 3.6.1、opencv_ive 算子案例介绍 * 本案例主要是中山旷视基于opencv开发的IVE算子加速API接口,方便开发者在调用opencv原生算子API的同时实现了IVE硬件加速的效果。 -### 2.6.2、目录 +### 3.6.2、目录 ```shell - +~/pegasus/vendor/zsks/demo/opencv_ive$ ls -lah +|── 001_dilate_demo # 膨胀操作算子 +|── 002_erode_demo # 腐蚀操作算子 +|── 003_sobel_demo # sobel边缘检测算子 +|── 004_bin_and_demo # 按位与操作算子 +|── 005_bin_or_demo # 按位或操作算子 +|── 006_bin_xor_demo # 按位异或操作算子 +|── 007_bin_sub_demo # 按位差操作算子 +|── 008_resize_demo # 图像缩放操作算子 +|── 009_ncc_demo # 归一化互相关操作算子 +|── 010_ccl_demo # 连通分量标记操作算子 +|── 011_filter_demo # 线性滤波操作算子 +|── 012_order_stats_filter_demo # 排序统计滤波操作算子 +|── 013_threshold_demo # 8位阈值操作算子 +|── 014_dma # DMA操作算子 +|── 015_threshold_s16_demo #带符号16位图像的阈值操作算子 +|── 016_threshold_u16_demo #无符号16位图像的阈值操作算子 +|── 017_16bit_to_8bit_demo # 位深转换操作算子 +|── 018_integ_demo # 积分图像操作算子 +|── 019_hist_demo # 直方图操作算子 +|── 020_map_demo # 映射变换操作算子 +|── 021_mag_and_ang # 幅度与角度操作算子 +|── 022_add_demo # 加法操作算子 +|── clang.cmake # clang的编译脚本 +|── CMakeLists.txt # CMake编译脚本 +|── cust_stat.sh # 案例板端推理脚本 +|── gcc.cmake # gcc的编译脚本 +└── Makefile # MakeFile编译脚本 ``` - - -### 2.6.3、编译 +### 3.6.3、编译 * **注意:在编译zsks的demo之前,请确保你已经按照[开发指南中的步骤](../../README.md#2开发指南)把补丁打入对应目录下了**。 * 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -* 步骤2:使用Makefile的方式进行单编 - * 在Ubuntu的命令行终端,分步执行下面的命令,编译 opencv_ive 下的所有案例 -* 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + ```sh + cd ~/pegasus/vendor/zsks/demo/opencv_ive - ``` - cd ~/pegasus/vendor/zsks/demo/opencv_ive - - make LLVM=1 clean && make LLVM=1 + cd ~/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64 + ln -s /home/hispark/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot sysroot + + # 当你开发板系统镜像烧录的是openharmony,按照下面的命令进行编译 + make clang + + # 当你开发板系统镜像烧录的是ubuntu/openeuler,按照下面的命令进行编译 + make gcc ``` * 在out/clang(out/gcc)目录下,生成一系列可执行文件,如下图所示: - + ![image-20260522144612990](pic/image-20260522144612990.png) -### 2.6.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 +### 3.6.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 **方式一:使用SD卡进行资料文件的拷贝** * 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 -image-20221114150205685 - -* 步骤1:将编译后生成的可执行文件main和资源文件data,拷贝到SD卡中。 +![image-20221114150205685-20260428155154-4qvikeh](pic/image-20221114150205685-20260428155154-4qvikeh.png) -![image-20251023100347550](pic/image-20251023100347550.png) +* 步骤1:将编译后生成的gcc/clang文件夹,以及opensoucre/opencv目录下对于的lib文件夹,拷贝到SD卡中。 * 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 -image-20250210161601541 +![image-20260428150712-7avg3km](pic/image-20260428150712-7avg3km.png) * 在开发板的终端,执行下面的命令进行SD卡的挂载 * 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) @@ -56,68 +82,43 @@ ```shell mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 ``` -* 挂载成功后,如下图所示: - -![image-20251023102549783](pic/image-20251023102549783.png) - **方式二:使用NFS挂载的方式进行资料文件的拷贝** * 首先需要自己准备一根网线 * 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -* 步骤2:将编译后生成的可执行文件main和资源文件data,拷贝到Windows的nfs共享路径下 - -![image-20251023100136196](pic/image-20251023100136196.png) +* 步骤2:将编译后生成的gcc/clang文件夹,以及opensoucre/opencv目录下对于的lib文件夹,拷贝到SD卡中。,拷贝到Windows的nfs共享路径下 -* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 +* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 * 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 -``` -ifconfig eth0 192.168.100.100 +```sh +ifconfig eth0 hw ether 00:d1:f3:09:bd:0c +ifconfig eth0 192.168.137.0 netmask 255.255.255.0 +route add default gw 192.168.137.1 -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +mount -o nolock,addr=192.168.137.1 -t nfs 192.168.137.1:/d/nfs /mnt ``` -![image-20251023101210815](pic/image-20251023101210815.png) +### 3.6.5、功能验证 -### 2.6.5、硬件连接 +* 在开发板的终端执行下面的命令,运行可执行文件的运行脚本 -* 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 +```sh +cp /mnt/lib /usr/ -rf -![image-20250213112932380](pic/image-20250213112932380.png) +# 如果是Ubuntu/openeuler系统 +cd /mnt/gcc -* 将USB 摄像头接在EulerPi开发板的USB接口上。 +# 如果是openharmony系统 +cd /mnt/clang -image-20250919150630870 +chmod +x cust_stat.sh -### 2.6.6、功能验证 - -* 在开发板的终端执行下面的命令,运行可执行文件 - -``` -cd /mnt - -chmod +x main - -./main +./cust_stat.sh ``` -![image-20251023101503216](pic/image-20251023101503216.png) - -* 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -image-20250210170027454 - -* 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 - -![image-20250919151018659](pic/image-20250919151018659.png) - -* 正常情况下,我们会在外接显示屏上看到人脸的区域被框出来,且在比较黑暗或者强逆光条件下,也能比较好的检测到人脸。![image-20250919151605632](pic/image-20250919151605632.png) - -* 敲两下回车即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310.png) +![image-20260522145457469](pic/image-20260522145457469.png) diff --git a/vendor/zsks/demo/opencv_ive/clang.cmake b/vendor/zsks/demo/opencv_ive/clang.cmake new file mode 100644 index 0000000000000000000000000000000000000000..26f3b3457f7b2b97123f40d8cbec918a1d11e78b --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/clang.cmake @@ -0,0 +1,8 @@ +# 这个文件是clang专用的配置文件,不适合gcc等其它编译器。 + +# 设置交叉编译器 +set(CUST_CROSS_TOOL_CHAIN_PATH "/home/hispark/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin") +set(CMAKE_C_COMPILER "${CUST_CROSS_TOOL_CHAIN_PATH}/aarch64-unknown-linux-ohos-clang" CACHE PATH "build tools" FORCE) +set(CMAKE_CXX_COMPILER "${CUST_CROSS_TOOL_CHAIN_PATH}/aarch64-unknown-linux-ohos-clang++" CACHE PATH "build tools" FORCE) + + diff --git a/vendor/zsks/demo/opencv_ive/cust_stat.sh b/vendor/zsks/demo/opencv_ive/cust_stat.sh new file mode 100644 index 0000000000000000000000000000000000000000..7c3d4128f1749b8abb30a891da0d63b5bad278d9 --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/cust_stat.sh @@ -0,0 +1,123 @@ +#! /bin/sh + +# 设置超时时间(秒) +TIMEOUT=60 + +# 输出文件 +OUTPUT_FILE="result.csv" + +# 循环次数 +LOOP_COUNT=0 + +# 手动列出所有demo目录(确保顺序正确) +demos=( + "001_dilate_demo" + "002_erode_demo" + "003_sobel_demo" + "004_bin_and_demo" + "005_bin_or_demo" + "006_bin_xor_demo" + "007_bin_sub_demo" + "008_resize_demo" + "009_ncc_demo" + "010_ccl_demo" + "011_filter_demo" + "012_order_stats_filter_demo" + "013_threshold_demo" + "014_dma" + "015_threshold_s16_demo" + "016_threshold_u16_demo" + "017_16bit_to_8bit_demo" + "018_integ_demo" + "019_hist_demo" + "020_map_demo" + "021_mag_and_ang" + "022_add_demo" +) + +# 运行一轮测试 +run_one_loop() { + echo "" + echo "======================================" + echo "第 ${LOOP_COUNT} 轮测试开始" + echo "======================================" + echo "" + + # 清空本轮输出文件 + > "$OUTPUT_FILE" + + for demo in "${demos[@]}"; do + if [ -d "$demo" ] && [ -x "$demo/elf" ]; then + # 运行程序并捕获输出,过滤掉mmz相关信息 + output=$(timeout $TIMEOUT "$demo/elf" 2>&1 | grep -v "mmz_userdev") + + # 提取加速比信息 + speedup=$(echo "$output" | grep "加速比") + + if [ -n "$speedup" ]; then + echo " ✓ $speedup" + echo "$speedup" >> "$OUTPUT_FILE" + else + echo " ✗ 未找到加速比输出" + fi + else + echo "跳过: $demo (目录不存在或无elf文件)" + fi + + # 检查是否有用户输入 'q' 或 'Q' + if read -t 0.1 -n 1 key 2>/dev/null; then + if [ "$key" = "q" ] || [ "$key" = "Q" ]; then + echo "" + echo "======================================" + echo "检测到退出命令,正在停止测试..." + echo "======================================" + return 1 + fi + fi + done + + echo "" + echo "======================================" + echo "第 ${LOOP_COUNT} 轮测试完成" + echo "======================================" + + return 0 +} + +# 主程序 +echo "======================================" +echo "OpenCV IVE 性能测试脚本 (循环模式)" +echo "超时时间: ${TIMEOUT}秒" +echo "输出文件: ${OUTPUT_FILE}" +echo "按 q 或 Q 退出测试" +echo "======================================" + +# 无限循环运行 +while true; do + LOOP_COUNT=$((LOOP_COUNT + 1)) + + # 运行一轮测试,如果返回非零则退出 + run_one_loop + if [ $? -ne 0 ]; then + echo "已停止测试,共运行 ${LOOP_COUNT} 轮" + exit 0 + fi + + # 每轮结束后检查输入 + echo "" + echo "--------------------------------------" + echo "按任意键停止,否则继续下一轮..." + echo "--------------------------------------" + + # 等待1秒,同时检测输入 + if read -t 1 -n 1 key 2>/dev/null; then + if [ "$key" = "q" ] || [ "$key" = "Q" ]; then + echo "" + echo "======================================" + echo "检测到退出命令,正在停止测试..." + echo "======================================" + echo "已停止测试,共运行 ${LOOP_COUNT} 轮" + exit 0 + fi + fi +done \ No newline at end of file diff --git a/vendor/zsks/demo/opencv_ive/gcc.cmake b/vendor/zsks/demo/opencv_ive/gcc.cmake new file mode 100644 index 0000000000000000000000000000000000000000..718b80a4a398545e54f30ae94ad4c18b3720883f --- /dev/null +++ b/vendor/zsks/demo/opencv_ive/gcc.cmake @@ -0,0 +1,9 @@ +# 这个文件是gcc专用的配置文件,不适合clang等其它编译器。 + +# 设置交叉编译器 +set(CUST_CROSS_TOOL_CHAIN_PATH "/home/hispark/openeuler_gcc_arm64le/bin") +set(CMAKE_C_COMPILER "${CUST_CROSS_TOOL_CHAIN_PATH}/aarch64-openeuler-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "${CUST_CROSS_TOOL_CHAIN_PATH}/aarch64-openeuler-linux-gnu-g++") +set(CUST_GDB_EXECUTABLE "${CUST_CROSS_TOOL_CHAIN_PATH}/aarch64-openeuler-linux-gnu-gdb") + + diff --git "a/vendor/zsks/demo/opencv_ive/opencv ive\347\256\227\345\255\220\347\241\254\344\273\266\345\212\240\351\200\237\344\273\243\347\240\201\347\274\226\350\257\221\346\214\207\345\257\274.md" "b/vendor/zsks/demo/opencv_ive/opencv ive\347\256\227\345\255\220\347\241\254\344\273\266\345\212\240\351\200\237\344\273\243\347\240\201\347\274\226\350\257\221\346\214\207\345\257\274.md" deleted file mode 100755 index 6a3235c0a887e3f129283126604e14dc1231ee63..0000000000000000000000000000000000000000 --- "a/vendor/zsks/demo/opencv_ive/opencv ive\347\256\227\345\255\220\347\241\254\344\273\266\345\212\240\351\200\237\344\273\243\347\240\201\347\274\226\350\257\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,170 +0,0 @@ -# 基于opencv算子实现ive硬件加速代码编译指导 - -* 注意:在操作本文档之前,请先确保您已经按照[开发指南的步骤](https://gitee.com/HiSpark/pegasus/blob/master/vendor/zsks/README.md#2%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97),把所有环境搭建好了。 - -## 步骤1:安装交叉编译链 - -- 在你服务器的命令行执行下面的命令,检查交叉编译器环境变量是否生效。 -- 如果生效,直接跳到步骤2 -- 如果没有生效,请按照下面的内容安装交叉编译链。 - -``` -which clang - -echo $SYSROOT_PATH - -aarch64-openeuler-linux-gnu-gcc -v -``` - -![image-20260421154020568](pic/image-20260421154020568.png) - -![image-20260421154253997](pic/image-20260421154253997.png) - -### 1.安装clang交叉编译链 - -1. 配置之前请先执行OpenHarmony编译,编译生成依赖的sysroot。 - - > ![img](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/OpenHarmony%20Small%E7%89%88%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/public_sys-resources/icon-note.gif) **说明:** 使用LLVM-Clang工具链来编译SDK sample时,会依赖OpenHarmony编译后的产物:os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,因此需要提前进行OpenHarmony编译。 - -2. 假设工具链的sysroot路径为`~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot`,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - - ``` - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - ``` - -3. 检查SYSROOT_PATH配置是否生效。 - - ``` - echo $SYSROOT_PATH - ``` - -### 2.安装gcc交叉编译链 - -- 点击[这里](https://gitee.com/openeuler/yocto-meta-openeuler/releases),按照下图下载0.1.8的arm64版本的所有压缩包。 - -![image-20251028104357994](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/Hi3403V100%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8D%97/figures/image-20251028104357994.png) - -- 将arm64版本的所有压缩包拷贝至Ubuntu 用户主目录下,执行下面命令合成交叉工具链压缩包并解压。 - -``` -cd ~ - -cat 1_openeuler_gcc_arm64le.tar.gz 2_openeuler_gcc_arm64le.tar.gz 3_openeuler_gcc_arm64le.tar.gz 4_openeuler_gcc_arm64le.tar.gz > openeuler_gcc_arm64le.tar.gz - -rm 1_openeuler_gcc_arm64le.tar.gz 2_openeuler_gcc_arm64le.tar.gz 3_openeuler_gcc_arm64le.tar.gz 4_openeuler_gcc_arm64le.tar.gz - -tar -xzvf openeuler_gcc_arm64le.tar.gz -rm -rf openeuler_gcc_arm64le.tar.gz -``` - -- 此时交叉编译工具链的可执行文件在`openeuler_gcc_arm64le/bin/`下。 - -![image-20251028175519101](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/Hi3403V100%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8D%97/figures/image-20251028175519101.png) - -- 执行下面命令打开`~/.bashrc`文件,将`export PATH="~/openeuler_gcc_arm64le/bin:$PATH"`添加到文件末尾。 - -``` -vim ~/.bashrc -``` - -![image-20251028175927006](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/Hi3403V100%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8D%97/figures/image-20251028175927006.png) - -- 执行下面命令生效环境。 - -``` -source ~/.bashrc -``` - -![image-20251028180026168](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/Hi3403V100%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8D%97/figures/image-20251028180026168.png) - -- 检查交叉编译工具链是否生效。 - -``` -aarch64-openeuler-linux-gnu-gcc -v -``` - -![image-20251028180045878](https://gitee.com/HiSpark/pegasus/raw/master/docs/zh-CN/Hi3403V100%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8D%97/figures/image-20251028180045878.png) - -## 步骤2:下载opencv_operator代码并完成源码编译 - -* 在服务器的命令行终端执行下面的命令,安装依赖软件 - -```sh -apt-get install time cmake -y -``` - -* 在服务器的命令行终端执行下面的命令,下载opencv_operator代码 - -```sh -cd ~ - -git clone https://gitee.com/zsks_3403/opencv_operator.git -``` - -![image-20260421155121008](pic/image-20260421155121008.png) - -* 在服务器的命令行终端执行下面的命令,编译opencv_operator代码 - - * 注意: - * **如果你要编译clang的库文件,就执行下面的命令** - - ```sh - cd ~/opencv_operator/1.opencv/tools.based.bash/bash - - ./1.使用cmake进行配置.bash clang - - ./2.使用cmake进行构建.bash clang - - ./4.使用cmake进行安装.bash clang - - ./5.打包成tgz便于部署.bash clang - ``` - - ![image-20260421161320999](pic/image-20260421161320999.png) - - * 编译完成后,会在~/opencv_operator/1.opencv/out目录下生成一个clang的文件夹,里面的install目录就是头文件和库文件,package就是我们打包的头文件和库文件 - - ![image-20260421162247951](pic/image-20260421162247951.png) - - * 如果你要编译gcc的库文件,就执行下面的命令 - - ```sh - cd ~/opencv_operator/1.opencv/tools.based.bash/bash - - ./1.使用cmake进行配置.bash gcc - - ./2.使用cmake进行构建.bash gcc - - ./4.使用cmake进行安装.bash gcc - - ./5.打包成tgz便于部署.bash gcc - ``` - - ![image-20260421162839008](pic/image-20260421162839008.png) - - * 编译完成后,会在~/opencv_operator/1.opencv/out目录下生成一个gcc的文件夹,里面的install目录就是头文件和库文件,package就是我们打包的头文件和库文件 - -![image-20260421163106149](pic/image-20260421163106149.png) - -## 步骤3:拷贝中山旷视适配的opencv库文件和头文件至pegasus代码仓 - -* 在服务器的命令行终端执行下面的命令,拷贝中山旷视适配的opencv库文件和头文件至pegasus代码仓 - -``` -mkdir ~/pegasus/vendor/opensource/zsks_opencv_operator/clang -p - -mkdir ~/pegasus/vendor/opensource/zsks_opencv_operator/gcc -P - -rm ~/opencv_operator/1.opencv/out/clang/install/lib/cmake -rf -cp ~/opencv_operator/1.opencv/out/clang/install/lib ~/pegasus/vendor/opensource/zsks_opencv_operator/clang/ -rf -cp ~/opencv_operator/1.opencv/out/clang/install/include ~/pegasus/vendor/opensource/zsks_opencv_operator/clang/ -rf - -rm ~/opencv_operator/1.opencv/out/gcc/install/lib/cmake -rf -cp ~/opencv_operator/1.opencv/out/gcc/install/lib ~/pegasus/vendor/opensource/zsks_opencv_operator/gcc/ -rf -cp ~/opencv_operator/1.opencv/out/gcc/install/include ~/pegasus/vendor/opensource/zsks_opencv_operator/gcc/ -rf -``` - -![image-20260421164413734](pic/image-20260421164413734.png) - -## 步骤4:参考[《opencv_ive算子案例指导》](./demo/opencv_ive/README.md) 开发案例 - diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20221114150205685-20260428155154-4qvikeh.png b/vendor/zsks/demo/opencv_ive/pic/image-20221114150205685-20260428155154-4qvikeh.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc4215c962c57ba0e31548fb98c29c789f149d9 Binary files /dev/null and b/vendor/zsks/demo/opencv_ive/pic/image-20221114150205685-20260428155154-4qvikeh.png differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421154020568.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421154020568.png deleted file mode 100755 index 32b6459e71b1f9bb80c2b672d0a91ac8bc850fdb..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421154020568.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421154253997.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421154253997.png deleted file mode 100755 index d5306109d8394814ba6c924acb9da02461f6582b..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421154253997.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421155121008.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421155121008.png deleted file mode 100755 index ed18b84b169aaa2e898d29aa219cc743ec0591ee..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421155121008.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421161320999.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421161320999.png deleted file mode 100755 index ce4fc3de25a0ac812828b41446f3b841aa9d706a..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421161320999.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421162247951.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421162247951.png deleted file mode 100755 index a5af0ca5cc8d90c922aff4b4b572b221b44bd56a..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421162247951.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421162839008.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421162839008.png deleted file mode 100755 index 78142edf706d03693bb400c5eaab358cd48c69c7..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421162839008.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421163106149.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421163106149.png deleted file mode 100755 index 8de462b41808253d59cf8f9169487a553c6e8d4b..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421163106149.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260421164413734.png b/vendor/zsks/demo/opencv_ive/pic/image-20260421164413734.png deleted file mode 100755 index 1b94d4a1f0c21dc37e675c5f865fe439ad11fb99..0000000000000000000000000000000000000000 Binary files a/vendor/zsks/demo/opencv_ive/pic/image-20260421164413734.png and /dev/null differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/opencv_ive/pic/image-20260428150712-7avg3km.png new file mode 100644 index 0000000000000000000000000000000000000000..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files /dev/null and b/vendor/zsks/demo/opencv_ive/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260522144612990.png b/vendor/zsks/demo/opencv_ive/pic/image-20260522144612990.png new file mode 100644 index 0000000000000000000000000000000000000000..bba6699af0f4332762ff2fe386cc9ffe2c5b937f Binary files /dev/null and b/vendor/zsks/demo/opencv_ive/pic/image-20260522144612990.png differ diff --git a/vendor/zsks/demo/opencv_ive/pic/image-20260522145457469.png b/vendor/zsks/demo/opencv_ive/pic/image-20260522145457469.png new file mode 100644 index 0000000000000000000000000000000000000000..2fdde70f0bd95630fce0d491137374720d0520d0 Binary files /dev/null and b/vendor/zsks/demo/opencv_ive/pic/image-20260522145457469.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/Makefile b/vendor/zsks/demo/sample_kcf_track/Makefile old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/README.md b/vendor/zsks/demo/sample_kcf_track/README.md old mode 100755 new mode 100644 index 50c71cb1bfdddd7fe8f1a427f91194a44f919f6c..c3b88091fa417f578095f73afabfd4a47a2af7a6 --- a/vendor/zsks/demo/sample_kcf_track/README.md +++ b/vendor/zsks/demo/sample_kcf_track/README.md @@ -1,145 +1,137 @@ -# 2.4、sample_kcf_track操作指导 - -# 2.4.1、sample_kcf_track程序简介 - -- sample_kcf_track 基于SS928V100平台开发,以zsks套件为例,sample_kcf_track 基于KCF+Track模型,通过USB Camera,将采集到的图片送到KCF+trak模型,实现对目标的实时跟踪效果。 - -# 2.4.2、目录 - -```shell -pegasus/vendor/zsks/demo/sample_kcf_track -|── main.c # sample_kcf_track的主入口 -|── Makefile # 编译脚本 -|── sample_kcf_track.c # sample_kcf_track业务代码 -|── sample_kcf_track.h # sample_kcf_track业务代码头文件 -|── sample_svp_npu_process.c # 调用SVP_NPU的业务代码 -└── sample_svp_npu_process.c # 调用SVP_NPU的头文件 -``` - -![image-20250919184816530](pic/image-20250919184816530-20260428161927-v05m991.png) - -- 根据外接显示屏的输出参数进行配置,比如说我的外接显示屏的输出是1080P60,如果smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c sample_common_svp_get_def_vo_cfg函数的intf_sync为OT_VO_OUT_1080P30,则需要把他修改为OT_VO_OUT_1080P60。 - -![image-20251023102053075](pic/image-20251023102053075-20260428161927-d21q774.png) - -# 2.4.3、编译 - -- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 -- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 -- 步骤2:使用Makefile的方式进行单编 -- 在Ubuntu的命令行终端,分步执行下面的命令,单编 sample_kcf_track -- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 - - ``` - cd pegasus/vendor/zsks/demo/sample_kcf_track - - # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 - export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - # 检查SYSROOT_PATH配置是否生效。 - echo $SYSROOT_PATH - - make LLVM=1 clean && make LLVM=1 - ``` - - - 在sample_kcf_track/out目录下,生成一个名为main的可执行文件,如下图所示: - - ![image-20251231155023771](pic/image-20251231155023771-20260428161927-prfh1pp.png) - - ![image-20251231155047164](pic/image-20251231155047164-20260428161927-2vpal5n.png) - -# 2.4.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 - -**方式一:使用SD卡进行资料文件的拷贝** - -- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 - -![image-20221114150205685](pic/image-20221114150205685-20260428161927-susmgdg.png) - -- 步骤1:将编译后生成的可执行文件main,拷贝到SD卡中。 - -![image-20251023100505047](pic/image-20251023100505047-20260428161927-nw9lh40.png) - -- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 - -![image](pic/image-20260428150712-7avg3km.png) - -- 在开发板的终端,执行下面的命令进行SD卡的挂载 - - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) - -```shell -mount -t vfat /dev/mmcblk1p1 /mnt -# 其中/dev/mmcblk1p1需要根据实际块设备号修改 -``` - -- 挂载成功后,如下图所示: - -![image-20251023114317633](pic/image-20251023114317633-20260428161927-ip93uos.png) - -**方式二:使用NFS挂载的方式进行资料文件的拷贝** - -- 首先需要自己准备一根网线 -- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 -- 步骤2:将编译后生成的可执行文件main,拷贝到Windows的nfs共享路径下 - -![image-20251023100536744](pic/image-20251023100536744-20260428161927-obhzwi3.png) - -- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 - - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 - -``` -ifconfig eth0 192.168.100.100 - -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251023114345977](pic/image-20251023114345977-20260428161927-0qsjs9b.png) - -# 2.4.5、硬件连接 - -- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 - -![image](pic/image-20260428151316-vwbp8qg.png) - -- 将USB 摄像头接在EulerPi开发板的USB接口上。 - -![image](pic/image-20260428151432-6nzax2h.png) - -# 2.4.6、功能验证 - -- 在开发板的终端执行下面的命令,运行可执行文件 - -``` -cd /mnt/demo_ohos/sample_kcf_track - -chmod +x ./out/main - -./out/main -``` - -![image-20251023114430657](pic/image-20251023114430657-20260428161927-ul8fb3v.png) - -- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: - -![image](pic/image-20260428151528-smzz9s8.png) - -- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 - -![image-20250919151018659](pic/image-20250919151018659-20260428161927-3a6jf82.png) - -- 正常情况下,我们会在外接显示屏上看到USB Camera采集到的画面。 -- 步骤1:按下键盘的空格键,会在屏幕的正中间显示一个红色的框框。 - -![image-20250919192349341](pic/image-20250919192349341-20260428161927-l59wdc6.png) - -- 步骤2:把需要跟踪的目标放在红色框框内,然后再按一下空格键,此时红色框会变绿,如果没有变,可以重复一次。 -- 步骤3:移动需要跟踪的目标,绿色框会跟着目标一起移动。 - -![image-20250919192115350](pic/image-20250919192137187-20260428161927-a7x5l9e.png) - -- 当目标不在sensor视野范围内,绿框会变成黄色。 - -![image-20250919192243361](pic/image-20250919192243361-20260428161927-2lao60j.png) - -- 输入Q键,即可关闭程序 - -![image-20250919151519310](pic/image-20250919151519310-20260428161927-uton0wg.png) +# 3.4、sample_kcf_track操作指导 + +# 3.4.1、sample_kcf_track程序简介 + +- sample_kcf_track 基于SS928V100平台开发,以zsks套件为例,sample_kcf_track 基于KCF+Track模型,通过USB Camera,将采集到的图片送到KCF+trak模型,实现对目标的实时跟踪效果。 + +# 3.4.2、目录 + +```shell +pegasus/vendor/zsks/demo/sample_kcf_track +|── main.c # sample_kcf_track的主入口 +|── Makefile # 编译脚本 +|── sample_kcf_track.c # sample_kcf_track业务代码 +|── sample_kcf_track.h # sample_kcf_track业务代码头文件 +|── sample_svp_npu_process.c # 调用SVP_NPU的业务代码 +└── sample_svp_npu_process.c # 调用SVP_NPU的头文件 +``` + +- 根据外接显示屏的输出参数进行配置,比如说我的外接显示屏的输出是1080P60,如果smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c sample_common_svp_get_def_vo_cfg函数的intf_sync为OT_VO_OUT_1080P30,则需要把他修改为OT_VO_OUT_1080P60。 + +![image-20251023102053075](pic/image-20251023102053075-20260428161927-d21q774.png) + +# 3.4.3、编译 + +- **注意:在编译zsks的demo之前,请确保你已经按照**​**[开发指南中的步骤](../../README.md#2开发指南)**​**把补丁打入对应目录下了**。 +- 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 +- 步骤2:使用Makefile的方式进行单编 +- 在Ubuntu的命令行终端,分步执行下面的命令,单编 sample_kcf_track +- 编译命令添加LLVM=1参数可使用clang工具链编译,而LLVM=0参数可使用gcc工具链编译,不使用LLVM参数默认使用gcc工具链编译,当前开发板系统对应clang,所以本教程统一使用LLVM=1参数编译。 + + ``` + cd pegasus/vendor/zsks/demo/sample_kcf_track + + # 假设工具链的sysroot路径为~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot,将工具链的sysroot设置到环境变量SYSROOT_PATH。 + export SYSROOT_PATH=~/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + # 检查SYSROOT_PATH配置是否生效。 + echo $SYSROOT_PATH + + make LLVM=1 clean && make LLVM=1 + ``` + + - 在sample_kcf_track/out目录下,生成一个名为main的可执行文件,如下图所示: + + ![image-20251231155047164](pic/image-20251231155047164-20260428161927-2vpal5n.png) + +# 3.4.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +- 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +- 步骤1:将编译后生成的可执行文件main,拷贝到SD卡中。 + +![image-20251023100505047](pic/image-20251023100505047-20260428161927-nw9lh40.png) + +- 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +![image](pic/image-20260428150712-7avg3km.png) + +- 在开发板的终端,执行下面的命令进行SD卡的挂载 + - 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +- 挂载成功后,如下图所示: + +![image-20251023114317633](pic/image-20251023114317633-20260428161927-ip93uos.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +- 首先需要自己准备一根网线 +- 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +- 步骤2:将编译后生成的可执行文件main,拷贝到Windows的nfs共享路径下 + +![image-20251023100536744](pic/image-20251023100536744-20260428161927-obhzwi3.png) + +- 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + - 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + +``` +ifconfig eth0 192.168.100.100 + +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251023114345977](pic/image-20251023114345977-20260428161927-0qsjs9b.png) + +# 3.4.5、硬件连接 + +- 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image](pic/image-20260428151316-vwbp8qg.png) + +- 将USB 摄像头接在EulerPi开发板的USB接口上。 + +![image](pic/image-20260428151432-6nzax2h.png) + +# 3.4.6、功能验证 + +- 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt/demo_ohos/sample_kcf_track + +chmod +x ./out/main + +./out/main +``` + +- 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +![image](pic/image-20260428151528-smzz9s8.png) + +- 如果您看到的现象和下图现象不一致,可以确认一下USB摄像头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659-20260428161927-3a6jf82.png) + +- 正常情况下,我们会在外接显示屏上看到USB Camera采集到的画面。 +- 步骤1:按下键盘的空格键,会在屏幕的正中间显示一个红色的框框。 + +![image-20250919192349341](pic/image-20250919192349341-20260428161927-l59wdc6.png) + +- 步骤2:把需要跟踪的目标放在红色框框内,然后再按一下空格键,此时红色框会变绿,如果没有变,可以重复一次。 +- 步骤3:移动需要跟踪的目标,绿色框会跟着目标一起移动。 + +![image-20250919192115350](pic/image-20250919192137187-20260428161927-a7x5l9e.png) + +- 当目标不在sensor视野范围内,绿框会变成黄色。 + +![image-20250919192243361](pic/image-20250919192243361-20260428161927-2lao60j.png) + +- 输入Q键,即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310-20260428161927-uton0wg.png) diff --git a/vendor/zsks/demo/sample_kcf_track/main.c b/vendor/zsks/demo/sample_kcf_track/main.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20221114150205685-20260428161927-susmgdg.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20221114150205685-20260428161927-susmgdg.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919151018659-20260428161927-3a6jf82.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919151018659-20260428161927-3a6jf82.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919151519310-20260428161927-uton0wg.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919151519310-20260428161927-uton0wg.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919184816530-20260428161927-v05m991.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919184816530-20260428161927-v05m991.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192137187-20260428161927-a7x5l9e.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192137187-20260428161927-a7x5l9e.png old mode 100755 new mode 100644 index 40ae9c3bd0c0aa31a35641ceb139f98b193505cf..5436bb18d9867ce310d6a9d90d95484b26d1c326 Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192137187-20260428161927-a7x5l9e.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192137187-20260428161927-a7x5l9e.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192243361-20260428161927-2lao60j.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192243361-20260428161927-2lao60j.png old mode 100755 new mode 100644 index a2231c40a1430a678ed005050c743925f2ff02e1..5b5183498736ef5fdac4e37c783185f0bf676165 Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192243361-20260428161927-2lao60j.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192243361-20260428161927-2lao60j.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192349341-20260428161927-l59wdc6.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192349341-20260428161927-l59wdc6.png old mode 100755 new mode 100644 index e5ba33632d982e6806c584cc20fe487bb61389d6..c455236e28ebce00005e1cb14c5a4372434455c2 Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192349341-20260428161927-l59wdc6.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20250919192349341-20260428161927-l59wdc6.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023100505047-20260428161927-nw9lh40.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023100505047-20260428161927-nw9lh40.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023100536744-20260428161927-obhzwi3.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023100536744-20260428161927-obhzwi3.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023102053075-20260428161927-d21q774.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023102053075-20260428161927-d21q774.png old mode 100755 new mode 100644 index 6fc62dd35e3dcfeb36a6e3ba1e7cea3e008660ed..bd5f4022245d5ecf9f08ae429a099d1bb436c31b Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023102053075-20260428161927-d21q774.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023102053075-20260428161927-d21q774.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114317633-20260428161927-ip93uos.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114317633-20260428161927-ip93uos.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114345977-20260428161927-0qsjs9b.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114345977-20260428161927-0qsjs9b.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114430657-20260428161927-ul8fb3v.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251023114430657-20260428161927-ul8fb3v.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251231155023771-20260428161927-prfh1pp.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251231155023771-20260428161927-prfh1pp.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20251231155047164-20260428161927-2vpal5n.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20251231155047164-20260428161927-2vpal5n.png old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428150712-7avg3km.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428150712-7avg3km.png old mode 100755 new mode 100644 index df435036941a44a6cb7417ceb227de759f7b23b7..4d247f98ae2d4ddbad0684473da0fa72123ab488 Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428150712-7avg3km.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428150712-7avg3km.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151316-vwbp8qg.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151316-vwbp8qg.png old mode 100755 new mode 100644 index 15f31ab2465ae782b7f989394636f63afb3adf56..d9685f02d7410d1873f90b5b2cc0280f159f26aa Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151316-vwbp8qg.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151316-vwbp8qg.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151432-6nzax2h.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151432-6nzax2h.png old mode 100755 new mode 100644 index d5caadbf1182a680d8500a5231e60f7e545caf88..a3fac08b2fef75aaa6d7d1e9bf5fb045e029ce82 Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151432-6nzax2h.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151432-6nzax2h.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151528-smzz9s8.png b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151528-smzz9s8.png old mode 100755 new mode 100644 index 77a7bef4a3847c61c98449b68dad4c61fb494d0c..5aeccc9c51038fd22fcc550a3e6c8a5039edb32e Binary files a/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151528-smzz9s8.png and b/vendor/zsks/demo/sample_kcf_track/pic/image-20260428151528-smzz9s8.png differ diff --git a/vendor/zsks/demo/sample_kcf_track/sample_kcf_track.c b/vendor/zsks/demo/sample_kcf_track/sample_kcf_track.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/sample_kcf_track.h b/vendor/zsks/demo/sample_kcf_track/sample_kcf_track.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/sample_svp_npu_process.c b/vendor/zsks/demo/sample_kcf_track/sample_svp_npu_process.c old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/sample_kcf_track/sample_svp_npu_process.h b/vendor/zsks/demo/sample_kcf_track/sample_svp_npu_process.h old mode 100755 new mode 100644 diff --git a/vendor/zsks/demo/smp_linux_user_space.mak b/vendor/zsks/demo/smp_linux_user_space.mak old mode 100755 new mode 100644 index b91a5bb6b10000c3ac8ffb4e6872cd04c6a29caa..bfcd19a1512f088419f21cbf6be6053e2b2b3135 --- a/vendor/zsks/demo/smp_linux_user_space.mak +++ b/vendor/zsks/demo/smp_linux_user_space.mak @@ -7,7 +7,7 @@ CXX_OBJS := $(CXX_SRCS:%.cpp=%.o) CFLAGS += $(COMM_INC) -MPI_LIBS += $(REL_LIB)/libss_hdmi.a +MPI_LIBS += -lss_hdmi MPI_LIBS += $(LIBS_LD_CFLAGS) .PHONY : clean all @@ -17,7 +17,7 @@ all: $(TARGET) $(TARGET):$(COMM_OBJ) $(OBJS) $(CXX_OBJS) | $(MKDIRS) @echo ... ld $@ @echo ... $(TARGET) - @$(CC) $(CFLAGS) -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) $(REL_LIB)/libsecurec.a -Wl,--end-group + @$(CXX) $(CFLAGS) $(CXXFLAGS) -L$(REL_LIB) -L$(REL_LIB)/svp_npu -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,-rpath-link=$(REL_LIB) -Wl,-rpath-link=$(REL_LIB)/svp_npu -Wl,--disable-new-dtags -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) -lsecurec -Wl,--end-group @echo ================= $(notdir $(TARGET_NAME)) build success ================= $(COMM_OBJ): %.o : %.c diff --git a/vendor/zsks/docs/clang/alsa-lib/README.md b/vendor/zsks/docs/clang/alsa-lib/README.md old mode 100644 new mode 100755 index b894c62598d52bc24be33c0224bada852085a78e..df0fe1e8c8c26ed76771effc9198e9e8f2dc31d9 --- a/vendor/zsks/docs/clang/alsa-lib/README.md +++ b/vendor/zsks/docs/clang/alsa-lib/README.md @@ -32,7 +32,7 @@ rm alsa-lib-1.1.7.tar.bz2 cd alsa-lib-1.1.7 ``` -![image-20251017172451263](pic/image-20251017172451263-20260309151259-y6705lx.png) + ### 步骤2:配置环境变量 @@ -49,8 +49,6 @@ export CXXFLAGS="--sysroot=$SYSROOT" export LDFLAGS="--sysroot=$SYSROOT" ~~~ -![image-20251017172745509](pic/image-20251017172745509-20260309151259-ksdr0o0.png) - - 在服务器的命令执行下面的命令,更新config文件 ```sh @@ -67,8 +65,6 @@ wget -O config.guess https://git.savannah.gnu.org/cgit/config.git/plain/config.g grep -i "ohos" config.sub ``` -![image-20251017172824538](pic/image-20251017172824538-20260309151259-im69i3j.png) - ![image-20251017172849064](pic/image-20251017172849064-20260309151259-20nh4ii.png) - 修改include/global.h,在头文件中添加如下内容 @@ -99,7 +95,7 @@ grep -i "ohos" config.sub CC=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang ``` -![image-20251017173155196](pic/image-20251017173155196-20260309151259-10a8bxe.png) + ### 步骤4:编译安装 @@ -113,10 +109,6 @@ mkdir install make DESTDIR=/root/pegasus/vendor/opensource/alsa-lib-1.1.7/install install ~~~ -![image-20250904165253761](pic/image-20250904165253761-20260309151259-9u5tetk.png) - -![image-20250904165432734](pic/image-20250904165432734-20260309151259-9drrcij.png) - - 编译成功后,会在install目录下生成下面的文件 ![image-20251214132742931](pic/image-20251214132742931-20260309151259-o322dgz.png) @@ -158,10 +150,6 @@ export LDFLAGS="--sysroot=$SYSROOT -L$ALSA_LIB_DIR/lib -Wl,-rpath=/data/alsa-lib export PKG_CONFIG_LIBDIR=$ALSA_LIB_DIR/lib/pkgconfig ~~~ -![image-20260428090107532](pic/image-20260428090107532.png) - -![image-20260428090309815](pic/image-20260428090309815.png) - - 在服务器的命令执行下面的命令,更新config文件 ```sh @@ -203,7 +191,7 @@ grep -i "ohos" config.sub PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR" ``` -![image-20260428091600399](pic/image-20260428091600399.png) + ### 步骤3:编译安装 diff --git "a/vendor/zsks/docs/clang/ffmpeg/FFmpeg_CPU\344\270\216\347\241\254\344\273\266\347\274\226\350\247\243\347\240\201\351\200\237\345\272\246\345\257\271\346\257\224.xlsx" "b/vendor/zsks/docs/clang/ffmpeg/FFmpeg_CPU\344\270\216\347\241\254\344\273\266\347\274\226\350\247\243\347\240\201\351\200\237\345\272\246\345\257\271\346\257\224.xlsx" old mode 100644 new mode 100755 diff --git a/vendor/zsks/docs/clang/ffmpeg/README.md b/vendor/zsks/docs/clang/ffmpeg/README.md old mode 100644 new mode 100755 index ebd47e8dbcd151de4dfc303df5f879f69f5e609a..76a466251f53b4caf61d9207be9a90e5361a2acc --- a/vendor/zsks/docs/clang/ffmpeg/README.md +++ b/vendor/zsks/docs/clang/ffmpeg/README.md @@ -1,799 +1,781 @@ -# FFmpeg移植 - -## 1、软硬件环境 - -* 开发板:zsks-hi3403开发板 -* 交叉编译工具链:OHOS (dev) clang version 15.0.4 - -* 编译链路径:pegasus/os/OpenHarmony/ohos/prebuilts/clang/ohos/linux-x86_64/llvm/bin -* Python版本:Python-3.13.2 -* 移植的ffmpeg版本:FFmpeg-6.0 - -## 2、安装依赖 - -* 由于在编译ffmpeg的时候,需要依赖其他第三方软件,因此在编译ffmpeg之前,我们先把它依赖的第三方软件全部交叉编译出来。 - -### 步骤1:交叉编译v4l2 - -* 可以参考[v4l2的移植文档](../libv4l2/README.md)的前两章节,完成v4l2的移植工作。 - -### 步骤2:交叉编译x264 - -* 在服务器的命令行执行下面的命令,下载源码,配置编译链 - -```sh -cd pegasus/vendor/opensource/ - -git clone https://code.videolan.org/videolan/x264.git - -cd x264 -``` - -* 修改config.sub文件,在125行添加 linux-ohos* | - -![image-20251021144741884](pic/image-20251021144741884.png) - -* 执行下面的命令,配置编译环境,对代码进行编译 - -```sh -CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang \ - --sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot" \ -CXX="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang++ \ - --sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot" \ -CFLAGS="-march=armv8-a -mfpu=neon" \ -./configure \ ---host=aarch64-linux-ohos \ ---prefix=$(pwd)/install \ ---enable-shared - -make -j$(nproc) && make install -``` - -![image-20251021150217681](pic/image-20251021150217681.png) - -* 编译成功后会在install目录下生成如下文件 - -![image-20251021154212147](pic/image-20251021154212147.png) - -### 步骤3:交叉编译x265 - -* 在服务器的命令行执行下面的命令,下载源码 - -```sh -cd ../ - -wget https://bitbucket.org/multicoreware/x265_git/downloads/x265_3.5.tar.gz - -tar xf x265_3.5.tar.gz - -rm x265_3.5.tar.gz - -cd x265_3.5 -``` - -![image-20251021154533551](pic/image-20251021154533551.png) - -![image-20251021154614257](pic/image-20251021154614257.png) - -* 将下面内容添加到 build/aarch64-linux/crosscompile.cmake文件中 -* 注意:里面的库、头文件等的绝对路径请根据自己服务器的实际情况进行修改。 - -```sh -# ============================================================================= -# CMake Cross-Compile Toolchain File for HiSilicon SS928V100 (OpenHarmony) -# Architecture: aarch64-linux-ohos -# ============================================================================= - -# 目标系统配置 -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR aarch64) -set(CMAKE_SYSTEM_VERSION 1) - -# ============================================================================= -# 编译器配置 (请根据实际路径调整) -# ============================================================================= -set(TOOLCHAIN_ROOT "/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm") -set(SYSROOT "/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot") - -# C 编译器 -set(CMAKE_C_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang") -set(CMAKE_C_COMPILER_TARGET "aarch64-unknown-linux-ohos") - -# C++ 编译器 -set(CMAKE_CXX_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang++") -set(CMAKE_CXX_COMPILER_TARGET "aarch64-unknown-linux-ohos") - -# 汇编器 -set(CMAKE_ASM_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang") - -# 归档工具 -set(CMAKE_AR "${TOOLCHAIN_ROOT}/bin/llvm-ar") -set(CMAKE_RANLIB "${TOOLCHAIN_ROOT}/bin/llvm-ranlib") -set(CMAKE_STRIP "${TOOLCHAIN_ROOT}/bin/llvm-strip") -set(CMAKE_OBJCOPY "${TOOLCHAIN_ROOT}/bin/llvm-objcopy") -set(CMAKE_NM "${TOOLCHAIN_ROOT}/bin/llvm-nm") - -# ============================================================================= -# 搜索路径配置 -# ============================================================================= -# 只搜索目标系统的路径,避免混入宿主机的库 -set(CMAKE_FIND_ROOT_PATH ${SYSROOT}) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # 使用宿主机的可执行文件 -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # 只搜索目标系统的库 -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # 只搜索目标系统的头文件 -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # 只搜索目标系统的 package - -# ============================================================================= -# 编译标志 -# ============================================================================= -# 基础 C 标志 -set(CMAKE_C_FLAGS_INIT - "--sysroot=${SYSROOT} -fPIC -march=armv8-a" -) - -# C++ 标志 -set(CMAKE_CXX_FLAGS_INIT - "--sysroot=${SYSROOT} -fPIC -march=armv8-a -std=c++11" -) - -# 汇编标志 -set(CMAKE_ASM_FLAGS_INIT - "--sysroot=${SYSROOT} -fPIC" -) - -# 链接标志 -set(CMAKE_EXE_LINKER_FLAGS_INIT - "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" -) - -set(CMAKE_SHARED_LINKER_FLAGS_INIT - "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" -) - -set(CMAKE_MODULE_LINKER_FLAGS_INIT - "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" -) - -# ============================================================================= -# 其他配置 -# ============================================================================= -# 启用位置无关代码 (共享库必需) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -# 禁用 rpath (交叉编译通常不需要) -set(CMAKE_SKIP_RPATH ON) -set(CMAKE_SKIP_INSTALL_RPATH ON) - -# 设置默认构建类型为 Release -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) -endif() - -# 打印配置信息 (调试用) -message(STATUS "Cross-compiling for: ${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}") -message(STATUS "Sysroot: ${SYSROOT}") -message(STATUS "C Compiler: ${CMAKE_C_COMPILER}") -message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}") -``` - -* 在服务器的命令行执行下面的命令,配置编译选项 - -```sh -cd /root/pegasus/vendor/opensource/x265_3.5 - -cmake ./source \ - -G "Unix Makefiles" \ - -DCMAKE_SYSTEM_NAME=Linux \ - -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ - -DCMAKE_SYSTEM_VERSION=ohos \ - -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ - -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ - -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ - -DCMAKE_INSTALL_PREFIX="$(pwd)/install" \ - -DENABLE_SHARED=ON \ - -DENABLE_PIC=ON \ - -DHIGH_BIT_DEPTH=ON \ - -DEXPORT_C_API=ON \ - -DENABLE_ASSEMBLY=OFF \ - -Wno-dev - -make -j$(nproc) && make install -``` - -![image-20251021161044799](pic/image-20251021161044799.png) - -![image-20251021161134241](pic/image-20251021161134241.png) - -* 编译完成后,会在install目录下生成如下文件 - -![image-20251021161216433](pic/image-20251021161216433.png) - -## 3、交叉编译FFmpeg - -### 步骤1:下载源码 - -* 在服务器的命令行执行下面的命令,下载ffmpeg源码 - -```sh -cd ../ - -git clone -b release/6.0 https://gitee.com/zhongshankuangshi/ffmpeg.git - -cd ffmpeg -``` - -![image-20251021205649485](pic/image-20251021205649485.png) - -### 步骤2:环境变量配置 - -* 注意这里出现的决定路径的地址,请根据自己服务器的具体情况进行修改。 - -```sh -export CC=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang -export CXX=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang++ -export AR=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-ar -export LD=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/lld -export RANLIB=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-ranlib -export STRIP=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-strip - -export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/x264/install/lib/pkgconfig:$PKG_CONFIG_PATH" -export CXXFLAGS="-I/root/pegasus/vendor/opensource/x264/install/include $CXXFLAGS" -export LDFLAGS="-L/root/pegasus/vendor/opensource/x264/install/lib $LDFLAGS" - -export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/x265_3.5/install/lib/pkgconfig:$PKG_CONFIG_PATH" -export CXXFLAGS="-I/root/pegasus/vendor/opensource/x265_3.5/install/include $CXXFLAGS" -export LDFLAGS="-L/root/pegasus/vendor/opensource/x265_3.5/install/lib $LDFLAGS" - -export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/v4l-utils/install/lib/pkgconfig:$PKG_CONFIG_PATH" -export CXXFLAGS="-I/root/pegasus/vendor/opensource/v4l-utils/install/include $CXXFLAGS" -export LDFLAGS="-L/root/pegasus/vendor/opensource/v4l-utils/install/lib $LDFLAGS" -``` - -![image-20251021205900311](pic/image-20251021205900311.png) - -### 步骤3:修改相关编译脚本 - -* 在pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common/makefile的第4行,添加一个fPIC选项到CFLAGS,如下图所示: - -![image-20251022142837408](pic/image-20251022142837408.png) - -* 然后进入到pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common目录下,执行 make clean && make 命令,重新生成.o文件 -* 注意:请根据自己服务器的实际情况修改里面的绝对路径 - -```sh -export PATH=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH - -export SYSROOT_PATH=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot - -cd /root/pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common - -make clean && make -``` - -![image-20251022150813007](pic/image-20251022150813007.png) - -* 在ffmpeg目录下创建一个build_ffmpeg.sh脚本,把下面的内容复制进去 - -* 注意:请根据自己服务器的实际情况修改里面的绝对路径 - -![image-20251022150910879](pic/image-20251022150910879.png) - -```sh -#!/usr/bin/env bash -set -euo pipefail - -# 安全目标: -# - 禁止 TEXTREL(避免运行时写代码段/触发 W^X / mprotect 检查) -# - 禁止可执行栈 -# - 只链接必要库,避免把 out/lib 里所有 .a/.so 无脑塞进共享库 -# -# 使用方式(示例): -# chmod +x build_ffmpeg_safe.sh -# ./build_ffmpeg_safe.sh -# -# 你可以通过环境变量覆盖路径(不改脚本也能用): -# TOOLCHAIN_ROOT=... SYSROOT=... HISI_SDK_BASE=... ./build_ffmpeg_safe.sh - -fail() { echo "✗ $*" >&2; exit 1; } -info() { echo "✓ $*"; } - -TOOLCHAIN_ROOT="${TOOLCHAIN_ROOT:-/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm}" -CROSS_PREFIX="${CROSS_PREFIX:-aarch64-unknown-linux-ohos}" -SYSROOT="${SYSROOT:-/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot}" - -HISI_SDK_BASE="${HISI_SDK_BASE:-/root/pegasus/platform/ss928v100_clang/smp/a55_linux}" -HISI_MPP_BASE="${HISI_MPP_BASE:-${HISI_SDK_BASE}/mpp}" -HISI_COMMON_DIR="${HISI_COMMON_DIR:-${HISI_SDK_BASE}/mpp/sample/common}" - -X264_PREFIX="${X264_PREFIX:-/root/pegasus/vendor/opensource/x264/install}" -X265_PREFIX="${X265_PREFIX:-/root/pegasus/vendor/opensource/x265_3.5/install}" -V4L2_PREFIX="${V4L2_PREFIX:-/root/pegasus/vendor/opensource/v4l-utils/install}" - -WORK_DIR="$(pwd)" -FFMPEG_SRC="${FFMPEG_SRC:-../ffmpeg}" -PREFIX="${PREFIX:-${WORK_DIR}/install}" - -CC="${CC:-${TOOLCHAIN_ROOT}/bin/${CROSS_PREFIX}-clang}" -CXX="${CXX:-${TOOLCHAIN_ROOT}/bin/${CROSS_PREFIX}-clang++}" -AR="${AR:-${TOOLCHAIN_ROOT}/bin/llvm-ar}" -RANLIB="${RANLIB:-${TOOLCHAIN_ROOT}/bin/llvm-ranlib}" -STRIP="${STRIP:-${TOOLCHAIN_ROOT}/bin/llvm-strip}" - -export CC CXX AR RANLIB STRIP - -# OpenHarmony/OHOS 工具链在很多项目里要求显式传 target + sysroot。 -# 否则像 FFmpeg 这种 configure 测试“能否链接可执行文件”时,会报: -# " is unable to create an executable file. C compiler test failed." -TARGET_TRIPLE="${TARGET_TRIPLE:-${CROSS_PREFIX}}" -CC_OHOS="${CC_OHOS:-${CC} --target=${TARGET_TRIPLE} --sysroot=${SYSROOT}}" -CXX_OHOS="${CXX_OHOS:-${CXX} --target=${TARGET_TRIPLE} --sysroot=${SYSROOT}}" - -command -v "$CC" >/dev/null 2>&1 || fail "找不到 CC: $CC" -command -v "$CXX" >/dev/null 2>&1 || fail "找不到 CXX: $CXX" -[ -d "$SYSROOT" ] || fail "SYSROOT 不存在: $SYSROOT" -[ -d "$HISI_COMMON_DIR" ] || fail "HISI_COMMON_DIR 不存在: $HISI_COMMON_DIR" - -SDK_LIB_DIR="${SDK_LIB_DIR:-${WORK_DIR}/hisi_sdk_lib}" -mkdir -p "$SDK_LIB_DIR" - -ALL_SDK_LIB_DIRS=( - "${HISI_MPP_BASE}/out/lib" - "${HISI_MPP_BASE}/out/lib/svp_npu" - "${HISI_COMMON_DIR}" -) - -# 仅链接“确实需要”的库(白名单) -# 说明: -# - 这里不要把 out/lib 里所有库都链进来,尤其是 .a,极易引入非 PIC -> TEXTREL -# - 如缺库导致 undefined symbol,再按报错把所需库加入白名单(优先 .so) -HISI_LIB_ALLOWLIST=( - securec - ot_base - ot_osal - ot_sys - ot_chnl - ot_rgn - ot_gdc - ot_vgs - ot_dis - ot_vpp - ot_vi - ot_isp - ot_vpss - ot_vo - ot_vedu - ot_rc - ot_venc - ot_h264e - ot_h265e - ot_jpege - ot_jpegd - ot_vfmw - ot_vdec - ot_irq - ot_mpi_isp - ss_ive - ss_dpu_rect - ss_dpu_match - ss_mau - svp_acl - ot_aio - ot_ai - ot_ao - ot_aenc - ot_adec - ot_acodec - ot_pwm - ot_piris - ss_mpi - ss_hdmi - ss_isp - ss_ae - ss_awb - ss_voice_engine - ss_calcflicker - sns_hy_s0603 - sns_os08a20 - sns_os04a10 - sns_imx347_slave - sns_sc450ai - sns_sc450ai_2l - ot_sensor_i2c - ss_extend_stats - ss_ir_auto - ss_bnr - ss_acs - ss_drc - ss_dehaze - ss_ldci - ss_crb - protobuf-c - ss_upvqe - ss_dnvqe -) - -export PKG_CONFIG_PATH="${X264_PREFIX}/lib/pkgconfig:${X265_PREFIX}/lib/pkgconfig:${V4L2_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH:-}" - -# 直接写死板端部署目录的绝对 rpath,避免 configure 的 eval 把 "$ORIGIN" 展开出各种问题。 -# 如你的实际部署目录不同,用环境变量覆盖: -# TARGET_RPATH_DIR=/mnt/ffmpeg/ffmpeg_install/lib TARGET_RPATH_NPU_DIR=/mnt/ffmpeg/lib/svp_npu ./build_ffmpeg_safe.sh -TARGET_RPATH_DIR="${TARGET_RPATH_DIR:-/usr/lib}" -TARGET_RPATH_NPU_DIR="${TARGET_RPATH_NPU_DIR:-/usr/lib/svp_npu}" -ABS_RPATH_FLAGS=( - "-Wl,-rpath,${TARGET_RPATH_DIR}" - "-Wl,-rpath,${TARGET_RPATH_NPU_DIR}" - "-Wl,--enable-new-dtags" -) - -readelf_textrel_check() { - local f="$1" - if readelf -dW "$f" 2>/dev/null | grep -qiE 'TEXTREL'; then - echo "检测到 TEXTREL(不安全):$f" >&2 - readelf -dW "$f" | grep -iE 'textrel|flags' >&2 || true - return 1 - fi - return 0 -} - -readelf_stack_check() { - local f="$1" - # 期望 GNU_STACK 是 RW(非可执行栈),如果出现 RWE 则失败 - if readelf -lW "$f" 2>/dev/null | grep -qE 'GNU_STACK.*RWE'; then - echo "检测到可执行栈(不安全):$f" >&2 - readelf -lW "$f" | grep -nE 'GNU_STACK|LOAD' >&2 || true - return 1 - fi - return 0 -} - -build_hisi_sdk_init_so() { - info "重新编译 common 目录目标文件(确保 -fPIC 生效)" - # common 目录源码会引用 mpp/out/include 下的头文件(例如 ot_common.h)。 - # 这里显式把必要 include 路径注入到 make,避免因为 Makefile.param/环境差异导致缺头文件。 - local common_includes=( - "-I${HISI_MPP_BASE}/out/include" - "-I${HISI_MPP_BASE}/include" - "-I${HISI_SDK_BASE}/include" - "-I${HISI_COMMON_DIR}" - ) - ( cd "$HISI_COMMON_DIR" && \ - make clean && \ - make CFLAGS+=" -fPIC $(printf '%s ' "${common_includes[@]}")" ) - - local objs=() - [ -f "${HISI_COMMON_DIR}/sdk_init.o" ] || fail "缺少 ${HISI_COMMON_DIR}/sdk_init.o" - [ -f "${HISI_COMMON_DIR}/sdk_exit.o" ] || fail "缺少 ${HISI_COMMON_DIR}/sdk_exit.o" - objs+=("${HISI_COMMON_DIR}/sdk_init.o" "${HISI_COMMON_DIR}/sdk_exit.o") - - # 如你确实需要把更多 .o 放进 so,可以保留,但更推荐只放必要初始化代码 - # 这里默认把 common 目录下其余 .o 也加进来(与原脚本行为一致),并用 -z,text 让非 PIC 直接报错 - while IFS= read -r -d '' obj; do - case "$(basename "$obj")" in - sdk_init.o|sdk_exit.o) : ;; - *) objs+=("$obj") ;; - esac - done < <(find "$HISI_COMMON_DIR" -maxdepth 1 -name '*.o' -print0) - - local link_libs=() - for lib in "${HISI_LIB_ALLOWLIST[@]}"; do - link_libs+=("-l${lib}") - done - - local out="${SDK_LIB_DIR}/libhisi_sdk_init.so" - rm -f "$out" - - info "生成 ${out}(禁止 TEXTREL,禁止可执行栈)" - # 关键点: - # -Wl,-z,text : 禁止 text relocation,出现非 PIC 直接失败并点名 - # -Wl,-z,noexecstack: 禁止可执行栈 - # -Wl,-z,relro -Wl,-z,now: 基础加固(可选,但一般安全无副作用) - # 关键:使用 --no-as-needed 强制把 SDK 库写入 DT_NEEDED, - # 否则链接器可能因为 --as-needed 优化掉“看起来没被直接引用”的库,导致板端报 Error relocating symbol not found。 - $CC_OHOS -shared -fPIC \ - -o "$out" \ - "${objs[@]}" \ - $(printf -- "-L%s " "${ALL_SDK_LIB_DIRS[@]}") \ - -Wl,--no-as-needed \ - "${link_libs[@]}" \ - -Wl,--as-needed \ - -lpthread -lm -ldl -lrt -lstdc++ \ - -Wl,--allow-shlib-undefined \ - -Wl,-allow-multiple-definition \ - -Wl,-z,text \ - -Wl,-z,noexecstack \ - -Wl,-z,relro -Wl,-z,now \ - "${ABS_RPATH_FLAGS[@]}" - - readelf_textrel_check "$out" || fail "libhisi_sdk_init.so 仍然含 TEXTREL,请按链接报错定位非 PIC 输入" - readelf_stack_check "$out" || fail "libhisi_sdk_init.so 存在可执行栈" - info "libhisi_sdk_init.so 通过安全检查" -} - -configure_ffmpeg() { - [ -x "${FFMPEG_SRC}/configure" ] || fail "找不到 FFmpeg configure: ${FFMPEG_SRC}/configure" - - # 仅对 ffmpeg 本身:同样禁止可执行栈 / relro/now - local extra_cflags="--sysroot=${SYSROOT} -fPIC -I${HISI_COMMON_DIR} -I${HISI_MPP_BASE}/out/include -DHISI_SDK_ENABLED" - local extra_ldflags="--sysroot=${SYSROOT} -L${SDK_LIB_DIR}" - for d in "${ALL_SDK_LIB_DIRS[@]}"; do - extra_ldflags+=" -L${d}" - done - extra_ldflags+=" -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now" - extra_ldflags+=" -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" - # 让 ffmpeg 优先从自身同目录加载依赖库(板端部署更稳) - extra_ldflags+=" ${ABS_RPATH_FLAGS[*]}" - - # 注意:这里不再把 out/lib 里所有库塞进来,只链接你真正需要的 hisi 初始化库; - # 其它依赖由 ffmpeg 在 link 阶段按需解析(若报 undefined,再把需要的库加入 allowlist 或按需加到 extra_ldflags) - extra_ldflags+=" -lhisi_sdk_init -lpthread -lm -ldl -lrt -lstdc++" - - info "配置 FFmpeg(输出安装到 ${PREFIX})" - ( cd "$WORK_DIR" && \ - "${FFMPEG_SRC}/configure" \ - --prefix="$PREFIX" \ - --arch=aarch64 \ - --target-os=linux \ - --enable-cross-compile \ - --disable-x86asm \ - --disable-static \ - --enable-shared \ - --cc="$CC_OHOS" \ - --cxx="$CXX_OHOS" \ - --strip="$STRIP" \ - --ld="$CXX" \ - --sysroot="$SYSROOT" \ - --enable-libx264 \ - --enable-libx265 \ - --enable-gpl \ - --enable-encoder=h264_ss928 \ - --enable-encoder=h265_ss928 \ - --enable-encoder=mjpeg_ss928 \ - --enable-decoder=h264_ss928 \ - --enable-decoder=h265_ss928 \ - --enable-decoder=mjpeg_ss928 \ - --extra-cflags="$extra_cflags" \ - --extra-ldflags="$extra_ldflags" \ - ) -} - -build_ffmpeg() { - info "开始编译并安装 FFmpeg" - make -j"$(nproc)" - make install - - # 基础安全自检:ffmpeg 可执行栈不应为 RWE - local ff="${PREFIX}/bin/ffmpeg" - if [ -f "$ff" ]; then - readelf_stack_check "$ff" || fail "ffmpeg 存在可执行栈" - info "ffmpeg 通过可执行栈检查" - else - info "未找到安装后的 ffmpeg(${ff}),跳过自检" - fi -} - -main() { - info "TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}" - info "SYSROOT=${SYSROOT}" - info "HISI_COMMON_DIR=${HISI_COMMON_DIR}" - info "SDK_LIB_DIR=${SDK_LIB_DIR}" - info "PREFIX=${PREFIX}" - - build_hisi_sdk_init_so - configure_ffmpeg - build_ffmpeg - - info "完成。若板端仍报错,优先检查安装目录下所有 .so 是否含 TEXTREL。" -} - -main "$@" -``` - -### 步骤4:编译ffmpeg - -* 在服务器的命令行,执行下面的命令,进行编译ffmpeg前的配置 - -```sh -chmod +x build_ffmpeg.sh - -./build_ffmpeg.sh -``` - -![image-20251022151107143](pic/image-20251022151107143.png) - -* 在服务器的命令行,执行下面的命令,进行ffmpeg的编译 - -```sh -make -j$(nproc) && make install -``` - -![image-20251022151357987](pic/image-20251022151357987.png) - -* 编译完成之后,会在install目录下生成下面的内容 - -![image-20251022151320279](pic/image-20251022151320279.png) - -* 并且在ffmpeg目录下生成一个hisi_sdk_lib的文件夹,里面有一个libhisi_sdk_init.so库 - -![image-20251022151540301](pic/image-20251022151540301.png) - -### 步骤5:编译sample - -* 在服务器的命令行,执行下面的命令,分别编译ffmpeg和hisi目录下的编解码案例 - -```sh -cd sample/ffmpeg - -make - -cd ../hisi - -make -``` - -![image-20251022155440903](pic/image-20251022155440903.png) - -![image-20251022155422517](pic/image-20251022155422517.png) - - - -## 4、板端验证 - -### 步骤1:配置板端环境 - -* 1、确保开发板已经烧录OpenHarmony操作系统 -* 2、使用网线将开发板与你的电脑进行连接,确保二者处于同一局域网内 -* 3、配置开发板的IP地址,并确保开发板与电脑能够互相ping通 - -```sh -# 注意:这里的eth0的IP地址,请根据自己的网络IP网段进行合理配置 -ifconfig eth0 192.168.100.100 - -# 添加权限 -echo 0 9999999 > /proc/sys/net/ipv4/ping_group_range -``` - -![image-20251010094441549](pic/image-20251010094441549.png) - -### 步骤2:准备ffmpeg依赖文件 - -* 1、将第2章交叉编译生成的v4l2、x264、x265的install目录,下载并拷贝到NFS挂载目录 -* 2、将第三章交叉编译ffmpeg生成的install目录,下载并拷贝到NFS挂载目录 -* 3、将第三章步骤5,编译好后的sample目录,下载并拷贝到NFS挂载目录 -* 4、将libhisi_sdk_init.so下载并拷贝到ffmpeg_install/lib/目录下 -* 5、将mpp/out/lib下载并拷贝到NFS挂载目录 - -![image-20251022162128690](pic/image-20251022162128690.png) - -![image-20251022164347161](pic/image-20251022164347161.png) - -* 6、在开发板的命令行终端执行下面的命令,将电脑的nfs目录挂载到开发板的/mnt目录下(注意:这里请根据自己的IP地址及NFS配置进行合理的修改) - -```sh -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251022162847658](pic/image-20251022162847658.png) - -* 因为我这里对每个库进行了打包,所以当我们把NFS挂载上后,需要对这些库进行解压才能正常使用 - -![image-20251022163123950](pic/image-20251022163123950.png) - -* 7、在开发板的命令行终端执行下面的命令,配置各个库的环境变量 - -```sh -export PATH=/mnt/ffmpeg/ffmpeg_install/bin:$PATH -export LD_LIBRARY_PATH=/mnt/ffmpeg/ffmpeg_install/lib:/mnt/ffmpeg/lib:/mnt/ffmpeg/lib/svp_npu:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/mnt/ffmpeg/v4l2_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/mnt/ffmpeg/x264_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/mnt/ffmpeg/x265_install/lib:$LD_LIBRARY_PATH - -chmod +x /mnt/ffmpeg/ffmpeg_install/bin/* -``` - -![image-20251022163146923](pic/image-20251022163146923.png) - -### 步骤3:测试ffmpeg是否正常工作 - -* 在开发板的命令行,执行下面的命令,获取ffmpeg的版本号 - -```sh -cd /mnt/ffmpeg/ffmpeg_install/bin/ - -ffmpeg -version -``` - -image-20251022170611820 - -### 步骤4:测试sample案例 - -* 注意:sample/hisi/目录下的是调用了海思硬件编解码模块,实现了硬件加速。sample/ffmpeg/目录下就是调用了ffmpeg的原始编解码接口。 -* 在开发板的命令行终端执行下面的命令,运行相关程序 - -```sh -cd /mnt/ffmpeg/sample/hisi - -chmod +x * - -# hisi编码 -./hisi_264venc /dev/video0 h264_ss928 640 480 30 - -cd /mnt/ffmpeg/sample/ffmpeg - -chmod +x * -# ffmpeg编码 -./264enc /dev/video0 640 480 30 -``` - -![image-20251022175239062](pic/image-20251022175239062.png) - -![image-20251022175457018](pic/image-20251022175457018.png) - -* 在开发板的命令行分步执行下面的命令,测试解码案例 - -```sh -cd /mnt/ffmpeg/sample/hisi - -# hisi解码 -./hisi_264vdec h264_ss928_output.h264 output - -# ffmpeg解码 -./264dec libx264_output.h264 output -``` - -![image-20251022175651926](pic/image-20251022175651926.png) - -![image-20251022175749466](pic/image-20251022175749466.png) - -* 如果想在自己的代码中使用ffmpeg调用hisi的硬件编解码模块,可以使用avcodec_find_decoder_by_name接口来实现 - -```c -avcodec_find_decoder_by_name("h264ss928"); - -avcodec_find_decoder_by_name("h265_ss928"); - -avcodec_find_decoder_by_name("mjpeg_ss928"); - -avcodec_find_encoder_by_name("h264_ss928"); - -avcodec_find_encoder_by_name("h265_ss928"); - -avcodec_find_encoder_by_name("mjpeg_ss928"); -``` - -## 5、海思硬件编解码与ffmpeg原生编解码对比 - -* decoder - -| 数据/解码器 | h264 | h264_ss928 | hevc | h265_ss928 | mjpeg | mjpeg_ss928 | -| ------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | -| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | -| 总处理帧数 | 85 | 207 | 21 | 221 | 125 | 217 | -| 总解码时间(ms) | 4547.785 | 8592.903 | 4566.406 | 9147.614 | 3020.907 | 93398.829 | -| 总发送时间(ms) | | | 4566.203 | 8168.024(89.3%) | | 9007.92 | -| 总接收时间(ms) | | | 0.203 | 1004.696(10.7%) | | 335.712 | -| 平均解码时间(ms/帧) | 53.503 | 41.512 | 217.448 | 41.401 | 20.167 | 43.036 | -| 平均发送时间(ms/帧) | | | 217.438 | 36.959 | | | -| 平均接收时间(ms/帧) | | | 0.01 | 4.546 | | | -| 最短解码时间(ms) | 0.036 | 40.653 | 191.937 | 40.699 | 22.408 | 40.909 | -| 最长解码时间(ms) | 74.43 | 42.67 | 307.397 | 44.188 | 26.027 | 83.292 | -| 时间差值(ms) | 12.534 | | 115.46 | 3.489 | 3.599 | 42.383 | -| 解码帧率(FPS) | 18.69 | 24.09 | 4.6 | 24.15 | 41.38 | 23.24 | -| 每秒处理像素(MP/s) | | | 9.54 | 50.09 | 19.09 | 12.52 | - -* encoder - -| 数据/编码器 | libx264 | h264_ss928 | libx265 | h265_ss928 | mjpeg | mjpeg_ss928 | -| ----------------------------- | ------------------------ | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | -| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | -| 总处理帧数 | 85 | 208 | 21 | 222 | 114 | 218 | -| 总耗时(s) | 30.45 | 14.05 | 41.62 | 15.56 | 16.36 | 15.1 | -| 平均FPS | 11.19 | 14.8 | 0.5 | 14.27 | 6.97 | 14.44 | -| 平均格式转换时间(ms/帧) | 3 | 65.22 | 11.52 | 66.91 | 51.11 | 66.17 | -| 平均编码时间(ms/帧) | 342.35 | 2.25 | 1957.39 | 3.07 | 89.4 | 2.99 | -| 编码效率(编码时间/理论帧间隔) | 1027.05% | 6.74% | 5872.18% | 9.20% | 268.21% | 8.97% | -| 总编码时间(s) | 29.01 | 0.47 | 41.11 | 0.68 | 10.19 | 0.65 | -| 总转换时间(s) | 0.95 | 13.57 | 0.24 | 14.85 | 5.83 | 14.43 | -| 输出文件大小(MB) | 1.26 | | 0.32 | 13.28 | 17.44 | 11.86 | -| 压缩比 | 39.29:1 | | 192.04:1 | 49.60:1 | 19.39:1 | 54.52:1 | -| 平均码率(kbps) | 347.13 | | 65.39 | 7158.57 | 8941.11 | 6589.71 | -| 性能评级 | 极高压缩率,编码需要优化 | 编码优秀 | 压缩良好,编码不足 | 编码优秀 | 需优化 | 优秀 | +# FFmpeg移植 + +## 1、软硬件环境 + +* 开发板:zsks-hi3403开发板 +* 交叉编译工具链:OHOS (dev) clang version 15.0.4 + +* 编译链路径:pegasus/os/OpenHarmony/ohos/prebuilts/clang/ohos/linux-x86_64/llvm/bin +* Python版本:Python-3.13.2 +* 移植的ffmpeg版本:FFmpeg-6.0 + +## 2、安装依赖 + +* 由于在编译ffmpeg的时候,需要依赖其他第三方软件,因此在编译ffmpeg之前,我们先把它依赖的第三方软件全部交叉编译出来。 + +### 步骤1:交叉编译v4l2 + +* 可以参考[v4l2的移植文档](../libv4l2/README.md)的前两章节,完成v4l2的移植工作。 + +### 步骤2:交叉编译x264 + +* 在服务器的命令行执行下面的命令,下载源码,配置编译链 + +```sh +cd pegasus/vendor/opensource/ + +git clone https://code.videolan.org/videolan/x264.git + +cd x264 +``` + +* 修改config.sub文件,在125行添加 linux-ohos* | + +![image-20251021144741884](pic/image-20251021144741884.png) + +* 执行下面的命令,配置编译环境,对代码进行编译 + +```sh +CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang \ + --sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot" \ +CXX="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang++ \ + --sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot" \ +CFLAGS="-march=armv8-a -mfpu=neon" \ +./configure \ +--host=aarch64-linux-ohos \ +--prefix=$(pwd)/install \ +--enable-shared + +make -j$(nproc) && make install +``` + +![image-20251021150217681](pic/image-20251021150217681.png) + +* 编译成功后会在install目录下生成如下文件 + +![image-20251021154212147](pic/image-20251021154212147.png) + +### 步骤3:交叉编译x265 + +* 在服务器的命令行执行下面的命令,下载源码 + +```sh +cd ../ + +wget https://bitbucket.org/multicoreware/x265_git/downloads/x265_3.5.tar.gz + +tar xf x265_3.5.tar.gz + +rm x265_3.5.tar.gz + +cd x265_3.5 +``` + +![image-20251021154533551](pic/image-20251021154533551.png) + +![image-20251021154614257](pic/image-20251021154614257.png) + +* 将下面内容添加到 build/aarch64-linux/crosscompile.cmake文件中 +* 注意:里面的库、头文件等的绝对路径请根据自己服务器的实际情况进行修改。 + +```sh +# ============================================================================= +# CMake Cross-Compile Toolchain File for HiSilicon SS928V100 (OpenHarmony) +# Architecture: aarch64-linux-ohos +# ============================================================================= + +# 目标系统配置 +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(CMAKE_SYSTEM_VERSION 1) + +# ============================================================================= +# 编译器配置 (请根据实际路径调整) +# ============================================================================= +set(TOOLCHAIN_ROOT "/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm") +set(SYSROOT "/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot") + +# C 编译器 +set(CMAKE_C_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang") +set(CMAKE_C_COMPILER_TARGET "aarch64-unknown-linux-ohos") + +# C++ 编译器 +set(CMAKE_CXX_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang++") +set(CMAKE_CXX_COMPILER_TARGET "aarch64-unknown-linux-ohos") + +# 汇编器 +set(CMAKE_ASM_COMPILER "${TOOLCHAIN_ROOT}/bin/aarch64-unknown-linux-ohos-clang") + +# 归档工具 +set(CMAKE_AR "${TOOLCHAIN_ROOT}/bin/llvm-ar") +set(CMAKE_RANLIB "${TOOLCHAIN_ROOT}/bin/llvm-ranlib") +set(CMAKE_STRIP "${TOOLCHAIN_ROOT}/bin/llvm-strip") +set(CMAKE_OBJCOPY "${TOOLCHAIN_ROOT}/bin/llvm-objcopy") +set(CMAKE_NM "${TOOLCHAIN_ROOT}/bin/llvm-nm") + +# ============================================================================= +# 搜索路径配置 +# ============================================================================= +# 只搜索目标系统的路径,避免混入宿主机的库 +set(CMAKE_FIND_ROOT_PATH ${SYSROOT}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # 使用宿主机的可执行文件 +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # 只搜索目标系统的库 +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # 只搜索目标系统的头文件 +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # 只搜索目标系统的 package + +# ============================================================================= +# 编译标志 +# ============================================================================= +# 基础 C 标志 +set(CMAKE_C_FLAGS_INIT + "--sysroot=${SYSROOT} -fPIC -march=armv8-a" +) + +# C++ 标志 +set(CMAKE_CXX_FLAGS_INIT + "--sysroot=${SYSROOT} -fPIC -march=armv8-a -std=c++11" +) + +# 汇编标志 +set(CMAKE_ASM_FLAGS_INIT + "--sysroot=${SYSROOT} -fPIC" +) + +# 链接标志 +set(CMAKE_EXE_LINKER_FLAGS_INIT + "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" +) + +set(CMAKE_SHARED_LINKER_FLAGS_INIT + "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" +) + +set(CMAKE_MODULE_LINKER_FLAGS_INIT + "--sysroot=${SYSROOT} -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" +) + +# ============================================================================= +# 其他配置 +# ============================================================================= +# 启用位置无关代码 (共享库必需) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# 禁用 rpath (交叉编译通常不需要) +set(CMAKE_SKIP_RPATH ON) +set(CMAKE_SKIP_INSTALL_RPATH ON) + +# 设置默认构建类型为 Release +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) +endif() + +# 打印配置信息 (调试用) +message(STATUS "Cross-compiling for: ${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}") +message(STATUS "Sysroot: ${SYSROOT}") +message(STATUS "C Compiler: ${CMAKE_C_COMPILER}") +message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}") +``` + +* 在服务器的命令行执行下面的命令,配置编译选项 + +```sh +cd /root/pegasus/vendor/opensource/x265_3.5 + +cmake ./source \ + -G "Unix Makefiles" \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ + -DCMAKE_SYSTEM_VERSION=ohos \ + -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ + -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ + -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ + -DCMAKE_INSTALL_PREFIX="$(pwd)/install" \ + -DENABLE_SHARED=ON \ + -DENABLE_PIC=ON \ + -DHIGH_BIT_DEPTH=ON \ + -DEXPORT_C_API=ON \ + -DENABLE_ASSEMBLY=OFF \ + -Wno-dev + +make -j$(nproc) && make install +``` + +* 编译完成后,会在install目录下生成如下文件 + +![image-20251021161216433](pic/image-20251021161216433.png) + +## 3、交叉编译FFmpeg + +### 步骤1:下载源码 + +* 在服务器的命令行执行下面的命令,下载ffmpeg源码 + +```sh +cd ../ + +git clone -b release/6.0 https://gitee.com/zhongshankuangshi/ffmpeg.git + +cd ffmpeg +``` + +### 步骤2:环境变量配置 + +* 注意这里出现的决定路径的地址,请根据自己服务器的具体情况进行修改。 + +```sh +export CC=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang +export CXX=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang++ +export AR=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-ar +export LD=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/lld +export RANLIB=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-ranlib +export STRIP=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-strip + +export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/x264/install/lib/pkgconfig:$PKG_CONFIG_PATH" +export CXXFLAGS="-I/root/pegasus/vendor/opensource/x264/install/include $CXXFLAGS" +export LDFLAGS="-L/root/pegasus/vendor/opensource/x264/install/lib $LDFLAGS" + +export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/x265_3.5/install/lib/pkgconfig:$PKG_CONFIG_PATH" +export CXXFLAGS="-I/root/pegasus/vendor/opensource/x265_3.5/install/include $CXXFLAGS" +export LDFLAGS="-L/root/pegasus/vendor/opensource/x265_3.5/install/lib $LDFLAGS" + +export PKG_CONFIG_PATH="/root/pegasus/vendor/opensource/v4l-utils/install/lib/pkgconfig:$PKG_CONFIG_PATH" +export CXXFLAGS="-I/root/pegasus/vendor/opensource/v4l-utils/install/include $CXXFLAGS" +export LDFLAGS="-L/root/pegasus/vendor/opensource/v4l-utils/install/lib $LDFLAGS" +``` + +### 步骤3:修改相关编译脚本 + +* 在pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common/makefile的第4行,添加一个fPIC选项到CFLAGS,如下图所示: + +![image-20251022142837408](pic/image-20251022142837408.png) + +* 然后进入到pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common目录下,执行 make clean && make 命令,重新生成.o文件 +* 注意:请根据自己服务器的实际情况修改里面的绝对路径 + +```sh +export PATH=/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH + +export SYSROOT_PATH=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot + +cd /root/pegasus/platform/ss928v100_clang/smp/a55_linux/mpp/sample/common + +make clean && make +``` + +* 在ffmpeg目录下创建一个build_ffmpeg.sh脚本,把下面的内容复制进去 + +* 注意:请根据自己服务器的实际情况修改里面的绝对路径 + +![image-20251022150910879](pic/image-20251022150910879.png) + +```sh +#!/usr/bin/env bash +set -euo pipefail + +# 安全目标: +# - 禁止 TEXTREL(避免运行时写代码段/触发 W^X / mprotect 检查) +# - 禁止可执行栈 +# - 只链接必要库,避免把 out/lib 里所有 .a/.so 无脑塞进共享库 +# +# 使用方式(示例): +# chmod +x build_ffmpeg_safe.sh +# ./build_ffmpeg_safe.sh +# +# 你可以通过环境变量覆盖路径(不改脚本也能用): +# TOOLCHAIN_ROOT=... SYSROOT=... HISI_SDK_BASE=... ./build_ffmpeg_safe.sh + +fail() { echo "✗ $*" >&2; exit 1; } +info() { echo "✓ $*"; } + +TOOLCHAIN_ROOT="${TOOLCHAIN_ROOT:-/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm}" +CROSS_PREFIX="${CROSS_PREFIX:-aarch64-unknown-linux-ohos}" +SYSROOT="${SYSROOT:-/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot}" + +HISI_SDK_BASE="${HISI_SDK_BASE:-/root/pegasus/platform/ss928v100_clang/smp/a55_linux}" +HISI_MPP_BASE="${HISI_MPP_BASE:-${HISI_SDK_BASE}/mpp}" +HISI_COMMON_DIR="${HISI_COMMON_DIR:-${HISI_SDK_BASE}/mpp/sample/common}" + +X264_PREFIX="${X264_PREFIX:-/root/pegasus/vendor/opensource/x264/install}" +X265_PREFIX="${X265_PREFIX:-/root/pegasus/vendor/opensource/x265_3.5/install}" +V4L2_PREFIX="${V4L2_PREFIX:-/root/pegasus/vendor/opensource/v4l-utils/install}" + +WORK_DIR="$(pwd)" +FFMPEG_SRC="${FFMPEG_SRC:-../ffmpeg}" +PREFIX="${PREFIX:-${WORK_DIR}/install}" + +CC="${CC:-${TOOLCHAIN_ROOT}/bin/${CROSS_PREFIX}-clang}" +CXX="${CXX:-${TOOLCHAIN_ROOT}/bin/${CROSS_PREFIX}-clang++}" +AR="${AR:-${TOOLCHAIN_ROOT}/bin/llvm-ar}" +RANLIB="${RANLIB:-${TOOLCHAIN_ROOT}/bin/llvm-ranlib}" +STRIP="${STRIP:-${TOOLCHAIN_ROOT}/bin/llvm-strip}" + +export CC CXX AR RANLIB STRIP + +# OpenHarmony/OHOS 工具链在很多项目里要求显式传 target + sysroot。 +# 否则像 FFmpeg 这种 configure 测试“能否链接可执行文件”时,会报: +# " is unable to create an executable file. C compiler test failed." +TARGET_TRIPLE="${TARGET_TRIPLE:-${CROSS_PREFIX}}" +CC_OHOS="${CC_OHOS:-${CC} --target=${TARGET_TRIPLE} --sysroot=${SYSROOT}}" +CXX_OHOS="${CXX_OHOS:-${CXX} --target=${TARGET_TRIPLE} --sysroot=${SYSROOT}}" + +command -v "$CC" >/dev/null 2>&1 || fail "找不到 CC: $CC" +command -v "$CXX" >/dev/null 2>&1 || fail "找不到 CXX: $CXX" +[ -d "$SYSROOT" ] || fail "SYSROOT 不存在: $SYSROOT" +[ -d "$HISI_COMMON_DIR" ] || fail "HISI_COMMON_DIR 不存在: $HISI_COMMON_DIR" + +SDK_LIB_DIR="${SDK_LIB_DIR:-${WORK_DIR}/hisi_sdk_lib}" +mkdir -p "$SDK_LIB_DIR" + +ALL_SDK_LIB_DIRS=( + "${HISI_MPP_BASE}/out/lib" + "${HISI_MPP_BASE}/out/lib/svp_npu" + "${HISI_COMMON_DIR}" +) + +# 仅链接“确实需要”的库(白名单) +# 说明: +# - 这里不要把 out/lib 里所有库都链进来,尤其是 .a,极易引入非 PIC -> TEXTREL +# - 如缺库导致 undefined symbol,再按报错把所需库加入白名单(优先 .so) +HISI_LIB_ALLOWLIST=( + securec + ot_base + ot_osal + ot_sys + ot_chnl + ot_rgn + ot_gdc + ot_vgs + ot_dis + ot_vpp + ot_vi + ot_isp + ot_vpss + ot_vo + ot_vedu + ot_rc + ot_venc + ot_h264e + ot_h265e + ot_jpege + ot_jpegd + ot_vfmw + ot_vdec + ot_irq + ot_mpi_isp + ss_ive + ss_dpu_rect + ss_dpu_match + ss_mau + svp_acl + ot_aio + ot_ai + ot_ao + ot_aenc + ot_adec + ot_acodec + ot_pwm + ot_piris + ss_mpi + ss_hdmi + ss_isp + ss_ae + ss_awb + ss_voice_engine + ss_calcflicker + sns_hy_s0603 + sns_os08a20 + sns_os04a10 + sns_imx347_slave + sns_sc450ai + sns_sc450ai_2l + ot_sensor_i2c + ss_extend_stats + ss_ir_auto + ss_bnr + ss_acs + ss_drc + ss_dehaze + ss_ldci + ss_crb + protobuf-c + ss_upvqe + ss_dnvqe +) + +export PKG_CONFIG_PATH="${X264_PREFIX}/lib/pkgconfig:${X265_PREFIX}/lib/pkgconfig:${V4L2_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH:-}" + +# 直接写死板端部署目录的绝对 rpath,避免 configure 的 eval 把 "$ORIGIN" 展开出各种问题。 +# 如你的实际部署目录不同,用环境变量覆盖: +# TARGET_RPATH_DIR=/mnt/ffmpeg/ffmpeg_install/lib TARGET_RPATH_NPU_DIR=/mnt/ffmpeg/lib/svp_npu ./build_ffmpeg_safe.sh +TARGET_RPATH_DIR="${TARGET_RPATH_DIR:-/usr/lib}" +TARGET_RPATH_NPU_DIR="${TARGET_RPATH_NPU_DIR:-/usr/lib/svp_npu}" +ABS_RPATH_FLAGS=( + "-Wl,-rpath,${TARGET_RPATH_DIR}" + "-Wl,-rpath,${TARGET_RPATH_NPU_DIR}" + "-Wl,--enable-new-dtags" +) + +readelf_textrel_check() { + local f="$1" + if readelf -dW "$f" 2>/dev/null | grep -qiE 'TEXTREL'; then + echo "检测到 TEXTREL(不安全):$f" >&2 + readelf -dW "$f" | grep -iE 'textrel|flags' >&2 || true + return 1 + fi + return 0 +} + +readelf_stack_check() { + local f="$1" + # 期望 GNU_STACK 是 RW(非可执行栈),如果出现 RWE 则失败 + if readelf -lW "$f" 2>/dev/null | grep -qE 'GNU_STACK.*RWE'; then + echo "检测到可执行栈(不安全):$f" >&2 + readelf -lW "$f" | grep -nE 'GNU_STACK|LOAD' >&2 || true + return 1 + fi + return 0 +} + +build_hisi_sdk_init_so() { + info "重新编译 common 目录目标文件(确保 -fPIC 生效)" + # common 目录源码会引用 mpp/out/include 下的头文件(例如 ot_common.h)。 + # 这里显式把必要 include 路径注入到 make,避免因为 Makefile.param/环境差异导致缺头文件。 + local common_includes=( + "-I${HISI_MPP_BASE}/out/include" + "-I${HISI_MPP_BASE}/include" + "-I${HISI_SDK_BASE}/include" + "-I${HISI_COMMON_DIR}" + ) + ( cd "$HISI_COMMON_DIR" && \ + make clean && \ + make CFLAGS+=" -fPIC $(printf '%s ' "${common_includes[@]}")" ) + + local objs=() + [ -f "${HISI_COMMON_DIR}/sdk_init.o" ] || fail "缺少 ${HISI_COMMON_DIR}/sdk_init.o" + [ -f "${HISI_COMMON_DIR}/sdk_exit.o" ] || fail "缺少 ${HISI_COMMON_DIR}/sdk_exit.o" + objs+=("${HISI_COMMON_DIR}/sdk_init.o" "${HISI_COMMON_DIR}/sdk_exit.o") + + # 如你确实需要把更多 .o 放进 so,可以保留,但更推荐只放必要初始化代码 + # 这里默认把 common 目录下其余 .o 也加进来(与原脚本行为一致),并用 -z,text 让非 PIC 直接报错 + while IFS= read -r -d '' obj; do + case "$(basename "$obj")" in + sdk_init.o|sdk_exit.o) : ;; + *) objs+=("$obj") ;; + esac + done < <(find "$HISI_COMMON_DIR" -maxdepth 1 -name '*.o' -print0) + + local link_libs=() + for lib in "${HISI_LIB_ALLOWLIST[@]}"; do + link_libs+=("-l${lib}") + done + + local out="${SDK_LIB_DIR}/libhisi_sdk_init.so" + rm -f "$out" + + info "生成 ${out}(禁止 TEXTREL,禁止可执行栈)" + # 关键点: + # -Wl,-z,text : 禁止 text relocation,出现非 PIC 直接失败并点名 + # -Wl,-z,noexecstack: 禁止可执行栈 + # -Wl,-z,relro -Wl,-z,now: 基础加固(可选,但一般安全无副作用) + # 关键:使用 --no-as-needed 强制把 SDK 库写入 DT_NEEDED, + # 否则链接器可能因为 --as-needed 优化掉“看起来没被直接引用”的库,导致板端报 Error relocating symbol not found。 + $CC_OHOS -shared -fPIC \ + -o "$out" \ + "${objs[@]}" \ + $(printf -- "-L%s " "${ALL_SDK_LIB_DIRS[@]}") \ + -Wl,--no-as-needed \ + "${link_libs[@]}" \ + -Wl,--as-needed \ + -lpthread -lm -ldl -lrt -lstdc++ \ + -Wl,--allow-shlib-undefined \ + -Wl,-allow-multiple-definition \ + -Wl,-z,text \ + -Wl,-z,noexecstack \ + -Wl,-z,relro -Wl,-z,now \ + "${ABS_RPATH_FLAGS[@]}" + + readelf_textrel_check "$out" || fail "libhisi_sdk_init.so 仍然含 TEXTREL,请按链接报错定位非 PIC 输入" + readelf_stack_check "$out" || fail "libhisi_sdk_init.so 存在可执行栈" + info "libhisi_sdk_init.so 通过安全检查" +} + +configure_ffmpeg() { + [ -x "${FFMPEG_SRC}/configure" ] || fail "找不到 FFmpeg configure: ${FFMPEG_SRC}/configure" + + # 仅对 ffmpeg 本身:同样禁止可执行栈 / relro/now + local extra_cflags="--sysroot=${SYSROOT} -fPIC -I${HISI_COMMON_DIR} -I${HISI_MPP_BASE}/out/include -DHISI_SDK_ENABLED" + local extra_ldflags="--sysroot=${SYSROOT} -L${SDK_LIB_DIR}" + for d in "${ALL_SDK_LIB_DIRS[@]}"; do + extra_ldflags+=" -L${d}" + done + extra_ldflags+=" -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now" + extra_ldflags+=" -Wl,--allow-shlib-undefined -Wl,-allow-multiple-definition" + # 让 ffmpeg 优先从自身同目录加载依赖库(板端部署更稳) + extra_ldflags+=" ${ABS_RPATH_FLAGS[*]}" + + # 注意:这里不再把 out/lib 里所有库塞进来,只链接你真正需要的 hisi 初始化库; + # 其它依赖由 ffmpeg 在 link 阶段按需解析(若报 undefined,再把需要的库加入 allowlist 或按需加到 extra_ldflags) + extra_ldflags+=" -lhisi_sdk_init -lpthread -lm -ldl -lrt -lstdc++" + + info "配置 FFmpeg(输出安装到 ${PREFIX})" + ( cd "$WORK_DIR" && \ + "${FFMPEG_SRC}/configure" \ + --prefix="$PREFIX" \ + --arch=aarch64 \ + --target-os=linux \ + --enable-cross-compile \ + --disable-x86asm \ + --disable-static \ + --enable-shared \ + --cc="$CC_OHOS" \ + --cxx="$CXX_OHOS" \ + --strip="$STRIP" \ + --ld="$CXX" \ + --sysroot="$SYSROOT" \ + --enable-libx264 \ + --enable-libx265 \ + --enable-gpl \ + --enable-encoder=h264_ss928 \ + --enable-encoder=h265_ss928 \ + --enable-encoder=mjpeg_ss928 \ + --enable-decoder=h264_ss928 \ + --enable-decoder=h265_ss928 \ + --enable-decoder=mjpeg_ss928 \ + --extra-cflags="$extra_cflags" \ + --extra-ldflags="$extra_ldflags" \ + ) +} + +build_ffmpeg() { + info "开始编译并安装 FFmpeg" + make -j"$(nproc)" + make install + + # 基础安全自检:ffmpeg 可执行栈不应为 RWE + local ff="${PREFIX}/bin/ffmpeg" + if [ -f "$ff" ]; then + readelf_stack_check "$ff" || fail "ffmpeg 存在可执行栈" + info "ffmpeg 通过可执行栈检查" + else + info "未找到安装后的 ffmpeg(${ff}),跳过自检" + fi +} + +main() { + info "TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}" + info "SYSROOT=${SYSROOT}" + info "HISI_COMMON_DIR=${HISI_COMMON_DIR}" + info "SDK_LIB_DIR=${SDK_LIB_DIR}" + info "PREFIX=${PREFIX}" + + build_hisi_sdk_init_so + configure_ffmpeg + build_ffmpeg + + info "完成。若板端仍报错,优先检查安装目录下所有 .so 是否含 TEXTREL。" +} + +main "$@" +``` + +### 步骤4:编译ffmpeg + +* 在服务器的命令行,执行下面的命令,进行编译ffmpeg前的配置 + +```sh +chmod +x build_ffmpeg.sh + +./build_ffmpeg.sh +``` + +* 在服务器的命令行,执行下面的命令,进行ffmpeg的编译 + +```sh +make -j$(nproc) && make install +``` + +* 编译完成之后,会在install目录下生成下面的内容 + +![image-20251022151320279](pic/image-20251022151320279.png) + +* 并且在ffmpeg目录下生成一个hisi_sdk_lib的文件夹,里面有一个libhisi_sdk_init.so库 + +![image-20251022151540301](pic/image-20251022151540301.png) + +### 步骤5:编译sample + +* 在服务器的命令行,执行下面的命令,分别编译ffmpeg和hisi目录下的编解码案例 + +```sh +cd sample/ffmpeg + +make + +cd ../hisi + +make +``` + + + + + +## 4、板端验证 + +### 步骤1:配置板端环境 + +* 1、确保开发板已经烧录OpenHarmony操作系统 +* 2、使用网线将开发板与你的电脑进行连接,确保二者处于同一局域网内 +* 3、配置开发板的IP地址,并确保开发板与电脑能够互相ping通 + +```sh +# 注意:这里的eth0的IP地址,请根据自己的网络IP网段进行合理配置 +ifconfig eth0 192.168.100.100 + +# 添加权限 +echo 0 9999999 > /proc/sys/net/ipv4/ping_group_range +``` + +![image-20251010094441549](pic/image-20251010094441549.png) + +### 步骤2:准备ffmpeg依赖文件 + +* 1、将第2章交叉编译生成的v4l2、x264、x265的install目录,下载并拷贝到NFS挂载目录 +* 2、将第三章交叉编译ffmpeg生成的install目录,下载并拷贝到NFS挂载目录 +* 3、将第三章步骤5,编译好后的sample目录,下载并拷贝到NFS挂载目录 +* 4、将libhisi_sdk_init.so下载并拷贝到ffmpeg_install/lib/目录下 +* 5、将mpp/out/lib下载并拷贝到NFS挂载目录 + +![image-20251022162128690](pic/image-20251022162128690.png) + +![image-20251022164347161](pic/image-20251022164347161.png) + +* 6、在开发板的命令行终端执行下面的命令,将电脑的nfs目录挂载到开发板的/mnt目录下(注意:这里请根据自己的IP地址及NFS配置进行合理的修改) + +```sh +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251022162847658](pic/image-20251022162847658.png) + +* 因为我这里对每个库进行了打包,所以当我们把NFS挂载上后,需要对这些库进行解压才能正常使用 + +![image-20251022163123950](pic/image-20251022163123950.png) + +* 7、在开发板的命令行终端执行下面的命令,配置各个库的环境变量 + +```sh +export PATH=/mnt/ffmpeg/ffmpeg_install/bin:$PATH +export LD_LIBRARY_PATH=/mnt/ffmpeg/ffmpeg_install/lib:/mnt/ffmpeg/lib:/mnt/ffmpeg/lib/svp_npu:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/ffmpeg/v4l2_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/ffmpeg/x264_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/mnt/ffmpeg/x265_install/lib:$LD_LIBRARY_PATH + +chmod +x /mnt/ffmpeg/ffmpeg_install/bin/* +``` + +### 步骤3:测试ffmpeg是否正常工作 + +* 在开发板的命令行,执行下面的命令,获取ffmpeg的版本号 + +```sh +cd /mnt/ffmpeg/ffmpeg_install/bin/ + +ffmpeg -version +``` + +image-20251022170611820 + +### 步骤4:测试sample案例 + +* 注意:sample/hisi/目录下的是调用了海思硬件编解码模块,实现了硬件加速。sample/ffmpeg/目录下就是调用了ffmpeg的原始编解码接口。 +* 在开发板的命令行终端执行下面的命令,运行相关程序 + +```sh +cd /mnt/ffmpeg/sample/hisi + +chmod +x * + +# hisi编码 +./hisi_264venc /dev/video0 h264_ss928 640 480 30 + +cd /mnt/ffmpeg/sample/ffmpeg + +chmod +x * +# ffmpeg编码 +./264enc /dev/video0 640 480 30 +``` + +![image-20251022175239062](pic/image-20251022175239062.png) + +![image-20251022175457018](pic/image-20251022175457018.png) + +* 在开发板的命令行分步执行下面的命令,测试解码案例 + +```sh +cd /mnt/ffmpeg/sample/hisi + +# hisi解码 +./hisi_264vdec h264_ss928_output.h264 output + +# ffmpeg解码 +./264dec libx264_output.h264 output +``` + +![image-20251022175651926](pic/image-20251022175651926.png) + +![image-20251022175749466](pic/image-20251022175749466.png) + +* 如果想在自己的代码中使用ffmpeg调用hisi的硬件编解码模块,可以使用avcodec_find_decoder_by_name接口来实现 + +```c +avcodec_find_decoder_by_name("h264ss928"); + +avcodec_find_decoder_by_name("h265_ss928"); + +avcodec_find_decoder_by_name("mjpeg_ss928"); + +avcodec_find_encoder_by_name("h264_ss928"); + +avcodec_find_encoder_by_name("h265_ss928"); + +avcodec_find_encoder_by_name("mjpeg_ss928"); +``` + +## 5、海思硬件编解码与ffmpeg原生编解码对比 + +* decoder + +| 数据/解码器 | h264 | h264_ss928 | hevc | h265_ss928 | mjpeg | mjpeg_ss928 | +| ------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | +| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | +| 总处理帧数 | 85 | 207 | 21 | 221 | 125 | 217 | +| 总解码时间(ms) | 4547.785 | 8592.903 | 4566.406 | 9147.614 | 3020.907 | 93398.829 | +| 总发送时间(ms) | | | 4566.203 | 8168.024(89.3%) | | 9007.92 | +| 总接收时间(ms) | | | 0.203 | 1004.696(10.7%) | | 335.712 | +| 平均解码时间(ms/帧) | 53.503 | 41.512 | 217.448 | 41.401 | 20.167 | 43.036 | +| 平均发送时间(ms/帧) | | | 217.438 | 36.959 | | | +| 平均接收时间(ms/帧) | | | 0.01 | 4.546 | | | +| 最短解码时间(ms) | 0.036 | 40.653 | 191.937 | 40.699 | 22.408 | 40.909 | +| 最长解码时间(ms) | 74.43 | 42.67 | 307.397 | 44.188 | 26.027 | 83.292 | +| 时间差值(ms) | 12.534 | | 115.46 | 3.489 | 3.599 | 42.383 | +| 解码帧率(FPS) | 18.69 | 24.09 | 4.6 | 24.15 | 41.38 | 23.24 | +| 每秒处理像素(MP/s) | | | 9.54 | 50.09 | 19.09 | 12.52 | + +* encoder + +| 数据/编码器 | libx264 | h264_ss928 | libx265 | h265_ss928 | mjpeg | mjpeg_ss928 | +| ----------------------------- | ------------------------ | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | +| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | +| 总处理帧数 | 85 | 208 | 21 | 222 | 114 | 218 | +| 总耗时(s) | 30.45 | 14.05 | 41.62 | 15.56 | 16.36 | 15.1 | +| 平均FPS | 11.19 | 14.8 | 0.5 | 14.27 | 6.97 | 14.44 | +| 平均格式转换时间(ms/帧) | 3 | 65.22 | 11.52 | 66.91 | 51.11 | 66.17 | +| 平均编码时间(ms/帧) | 342.35 | 2.25 | 1957.39 | 3.07 | 89.4 | 2.99 | +| 编码效率(编码时间/理论帧间隔) | 1027.05% | 6.74% | 5872.18% | 9.20% | 268.21% | 8.97% | +| 总编码时间(s) | 29.01 | 0.47 | 41.11 | 0.68 | 10.19 | 0.65 | +| 总转换时间(s) | 0.95 | 13.57 | 0.24 | 14.85 | 5.83 | 14.43 | +| 输出文件大小(MB) | 1.26 | | 0.32 | 13.28 | 17.44 | 11.86 | +| 压缩比 | 39.29:1 | | 192.04:1 | 49.60:1 | 19.39:1 | 54.52:1 | +| 平均码率(kbps) | 347.13 | | 65.39 | 7158.57 | 8941.11 | 6589.71 | +| 性能评级 | 极高压缩率,编码需要优化 | 编码优秀 | 压缩良好,编码不足 | 编码优秀 | 需优化 | 优秀 | diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232849-tjfqh3n.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232849-tjfqh3n.png old mode 100644 new mode 100755 diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232913-7et18x6.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232913-7et18x6.png old mode 100644 new mode 100755 diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232951-jif09al.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915232951-jif09al.png old mode 100644 new mode 100755 diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915233247-0qbuniv.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20250915233247-0qbuniv.png old mode 100644 new mode 100755 diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20251010094441549.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20251010094441549.png index e981001ec636db595d2766310bf95a49e58f3914..63e1eaef2664fcd548632148c151d55fb61a91f5 100755 Binary files a/vendor/zsks/docs/clang/ffmpeg/pic/image-20251010094441549.png and b/vendor/zsks/docs/clang/ffmpeg/pic/image-20251010094441549.png differ diff --git a/vendor/zsks/docs/clang/ffmpeg/pic/image-20251021205900311.png b/vendor/zsks/docs/clang/ffmpeg/pic/image-20251021205900311.png index 995d820967e8a942a065956d51b38d48757d76a3..40aec69e251526ffd4d182524620bdebfa4a6dc8 100755 Binary files a/vendor/zsks/docs/clang/ffmpeg/pic/image-20251021205900311.png and b/vendor/zsks/docs/clang/ffmpeg/pic/image-20251021205900311.png differ diff --git a/vendor/zsks/docs/clang/libcamera/README.md b/vendor/zsks/docs/clang/libcamera/README.md index ee2ff59bdfdd368ae4165f95e7dc1f047cd69f56..4dfe413e568c5d54e205ac623c5e68207c6da335 100755 --- a/vendor/zsks/docs/clang/libcamera/README.md +++ b/vendor/zsks/docs/clang/libcamera/README.md @@ -20,8 +20,6 @@ cd pegasus/vendor/opensource/Python-3.13.2 . crossenv_aarch64/bin/activate ``` -![image-20251020160523558](pic/image-20251020160523558.png) - ## 3.安装依赖 * 由于在编译libacamera的时候,需要依赖其他第三方软件,因此在编译libacamera之前,我们先把它依赖的第三方软件全部交叉编译出来。 @@ -62,7 +60,7 @@ cd libevent-2.1.12-stable export CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin/aarch64-unknown-linux-ohos-clang --sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_hispark_aifly_linux/sysroot" ``` -![image-20251020162138430](pic/image-20251020162138430.png) + ![image-20251020162307165](pic/image-20251020162307165.png) @@ -86,10 +84,6 @@ sed -i 's/arc4random_buf/libevent_arc4random_buf/g' evutil_rand.c make && make install ``` -![image-20251020162558010](pic/image-20251020162558010.png) - -![image-20251020162712286](pic/image-20251020162712286.png) - * 编译成功后,会在install目录下生成以下文件 ![image-20251020163215884](pic/image-20251020163215884.png) @@ -109,8 +103,6 @@ rm tiff-4.5.1.tar.gz cd tiff-4.5.1 ``` -![image-20251020163840912](pic/image-20251020163840912.png) - * 在./config/config.sub文件中添加OHOS的编译依赖,确保编译时不会报错 * 在1761行添加 | ohos* * 在1782行添加 | linux-ohos* @@ -127,8 +119,6 @@ make && make install ![image-20251020164718454](pic/image-20251020164718454.png) -![image-20251020164811557](pic/image-20251020164811557.png) - * 编译完成后,会在install目录下生成如下的文件 ![image-20251020165144726](pic/image-20251020165144726.png) @@ -148,8 +138,6 @@ rm jpegsrc.v9d.tar.gz cd jpeg-9d ``` -![image-20251020165513929](pic/image-20251020165513929.png) - * 在服务器的命令行执行下面的命令,修改配置脚本和部分代码,确保编译时不会报错 ```sh @@ -170,10 +158,6 @@ export CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/b make && make install ``` -![image-20251020165719960](pic/image-20251020165719960.png) - -![image-20251020165802562](pic/image-20251020165802562.png) - * 编译完成后,会在install目录下生成如下的文件 ![image-20251020165955883](pic/image-20251020165955883.png) @@ -199,12 +183,6 @@ make CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin make install ``` -![image-20251009173438071](pic/image-20251009173438071.png) - -![image-20251009173659012](pic/image-20251009173659012.png) - -![image-20251009174036856](pic/image-20251009174036856.png) - ![image-20251009174105488](pic/image-20251009174105488.png) ### 步骤3:安装依赖软件 @@ -223,8 +201,6 @@ python -m pip install \ meson==1.6 jinja2 pyyaml ply pybind11 ``` -![image-20251020170606044](pic/image-20251020170606044.png) - ## 4、交叉编译libcamera ### 步骤1:下载源码 @@ -239,8 +215,6 @@ git clone https://git.libcamera.org/libcamera/libcamera.git cd libcamera ``` -![image-20251020172340245](pic/image-20251020172340245.png) - ### 步骤2:配置编译环境 * 在libcamera目录下创建一个cross_file.txt文件,然后把下面的内容复制进去。 diff --git a/vendor/zsks/docs/clang/libcamera/pic/image-20251021105919871.png b/vendor/zsks/docs/clang/libcamera/pic/image-20251021105919871.png index 6048787f578fa0534a0c728261b06812c4bdb0de..ea0477762d3a73ff2f105cca1520f49a2fe31009 100755 Binary files a/vendor/zsks/docs/clang/libcamera/pic/image-20251021105919871.png and b/vendor/zsks/docs/clang/libcamera/pic/image-20251021105919871.png differ diff --git a/vendor/zsks/docs/clang/libv4l2/README.md b/vendor/zsks/docs/clang/libv4l2/README.md old mode 100644 new mode 100755 index 35dab2f2023d1fbebb6fccc18f3710d1565e03a9..b0cb5d26e5c7ee0a0926743291555913206e0b22 --- a/vendor/zsks/docs/clang/libv4l2/README.md +++ b/vendor/zsks/docs/clang/libv4l2/README.md @@ -90,8 +90,6 @@ rm argp-standalone-1.3.tar.gz cd argp-standalone-1.3 ``` -![image-20251017153708743](pic/image-20251017153708743.png) - * 在服务器的命令行分步执行下面的命令,配置环境变量 ```sh @@ -106,8 +104,6 @@ export CXXFLAGS="--sysroot=$SYSROOT" export LDFLAGS="--sysroot=$SYSROOT" ``` -![image-20251017154000326](pic/image-20251017154000326.png) - * 在服务器的命令行分步执行下面的命令,对argp代码进行编译 ~~~bash @@ -122,9 +118,7 @@ export LDFLAGS="--sysroot=$SYSROOT" make -j$(nproc) && make install ~~~ -![image-20251017154359756](pic/image-20251017154359756.png) -![image-20251017154546402](pic/image-20251017154546402.png) * 在服务器的命令行分步执行下面的命令,复制argp.h和libargp.a到sysroot对应目录下 @@ -177,7 +171,7 @@ ninja -C build ninja -C build install ~~~ -![image-20251017155057453](pic/image-20251017155057453.png) + ![image-20251017163810406](pic/image-20251017163810406.png) diff --git a/vendor/zsks/docs/clang/numpy/README.md b/vendor/zsks/docs/clang/numpy/README.md index 65ceb57b6f1b4206297bb6f13bdaebe37fa462a4..3c91b2edd209564b8617aff2e1937ad4247fc3f4 100755 --- a/vendor/zsks/docs/clang/numpy/README.md +++ b/vendor/zsks/docs/clang/numpy/README.md @@ -31,9 +31,7 @@ git submodule update --init git checkout v2.2.5 ``` -![image-20251010105452576](pic/image-20251010105452576.png) -![image-20251010105525630](pic/image-20251010105525630.png) ### 步骤2:配置编译脚本 @@ -180,8 +178,6 @@ export PYTHONPATH=/mnt/install/lib/python3.13:$PYTHONPATH export LD_LIBRARY_PATH=/mnt/install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH ``` -image-20251010101732852 - ### 步骤3:使用python调用numpy接口: * 先输入python,进入板端python环境,然后输入import numpy 敲回车,如果没有任何报错,说明numpy移植成功 diff --git a/vendor/zsks/docs/clang/numpy/pic/image-20251010094441549.png b/vendor/zsks/docs/clang/numpy/pic/image-20251010094441549.png index e981001ec636db595d2766310bf95a49e58f3914..63e1eaef2664fcd548632148c151d55fb61a91f5 100755 Binary files a/vendor/zsks/docs/clang/numpy/pic/image-20251010094441549.png and b/vendor/zsks/docs/clang/numpy/pic/image-20251010094441549.png differ diff --git a/vendor/zsks/docs/clang/numpy/pic/image-20251010105452576.png b/vendor/zsks/docs/clang/numpy/pic/image-20251010105452576.png index 220d510fc77baff9461ee6909320d22b21c44fb1..648f4bd0aec312957c073f38adfe22c0607e589b 100755 Binary files a/vendor/zsks/docs/clang/numpy/pic/image-20251010105452576.png and b/vendor/zsks/docs/clang/numpy/pic/image-20251010105452576.png differ diff --git a/vendor/zsks/docs/clang/opencv/README.md b/vendor/zsks/docs/clang/opencv/README.md index b3599fe61e609ee5769fb3dcd81174c4edf65ddd..0059ccc430c56766611eadefcd5550b21446b841 100755 --- a/vendor/zsks/docs/clang/opencv/README.md +++ b/vendor/zsks/docs/clang/opencv/README.md @@ -21,7 +21,7 @@ python版本:Python-3.13.2 apt-get install cmake libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev python3-dev python3-numpy libdc1394-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev -y ``` -![image-20251013144111854](pic/image-20251013144111854.png) + * 先进入到python目录下,确保虚拟环境已经开启,关于如何搭建虚拟环境,可参考[numpy移植文档第2章的步骤3](../numpy/README.md)。 @@ -31,7 +31,7 @@ cd opensource/Python-3.13.2 . crossenv_aarch64/bin/activate ``` -![image-20251016145037570](pic/image-20251016145037570.png) + ### 步骤2:下载OpenCV源码 @@ -95,7 +95,7 @@ cmake ${SOURCE_DIR} \ make -j$(nproc) ``` -![image-20260424144350570](pic/image-20260424144350570.png) + * 出现下面的打印信息,说明OpenCV交叉编译成功: @@ -109,8 +109,6 @@ cd build make install ``` -![image-20251013150714220](pic/image-20251013150714220.png) - * 安装成功后,会在install目录下生成以下文件。 ![image-20251013150935466](pic/image-20251013150935466.png) diff --git a/vendor/zsks/docs/clang/opencv/pic/image-20251013150632408.png b/vendor/zsks/docs/clang/opencv/pic/image-20251013150632408.png index 8a388cfeb9b9c11c14cbc381728e54382c8cb187..7014a202a30a37bd0fac53d3d9b4ce272f037cfd 100755 Binary files a/vendor/zsks/docs/clang/opencv/pic/image-20251013150632408.png and b/vendor/zsks/docs/clang/opencv/pic/image-20251013150632408.png differ diff --git a/vendor/zsks/docs/clang/opencv/pic/image-20251016153355942.png b/vendor/zsks/docs/clang/opencv/pic/image-20251016153355942.png index f5d5f95bb5c5732a4f3fa9782d9c8bf932ac4bb2..1ea26bca19a3cc3b8541e25feaa278843d5f480d 100755 Binary files a/vendor/zsks/docs/clang/opencv/pic/image-20251016153355942.png and b/vendor/zsks/docs/clang/opencv/pic/image-20251016153355942.png differ diff --git a/vendor/zsks/docs/clang/opencv/pic/image-20251016153418154.png b/vendor/zsks/docs/clang/opencv/pic/image-20251016153418154.png index 764009360a2028ccb7ed14fe1d70d4e4604216f0..d2ad3025f4ffa1cd7047e536a4d25b58175a2a25 100755 Binary files a/vendor/zsks/docs/clang/opencv/pic/image-20251016153418154.png and b/vendor/zsks/docs/clang/opencv/pic/image-20251016153418154.png differ diff --git "a/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/OpenHarmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" "b/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/OpenHarmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" index 4d6a992a7f83eeca9d5f73784204bde93a1bd69d..d2b59f22ee08c73b03aec03038ea821842c5ebb6 100755 --- "a/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/OpenHarmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" +++ "b/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/OpenHarmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" @@ -408,13 +408,13 @@ rm out -rf * 第一次烧写完成后,需要配置bootargs,脚本如下 ```sh -setenv bootargs 'mem=512M console=ttyAMA0,115200 clk_ignore_unused rw rootwait root=/dev/mmcblk0p4 rootfstype=ext4 blkdevparts=mmcblk0:512K(fastboot),512K(env),20M(kernel),1024M(rootfs),50M(userfs),-(userdata)'; +env default -a; +setenv bootargs 'mem=512M console=ttyAMA0,115200 clk_ignore_unused rw rootwait root=/dev/mmcblk0p4 rootfstype=ext4 blkdevparts=mmcblk0:512K(fastboot),512K(env),20M(kernel),2048M(rootfs),50M(userfs),-(userdata)'; setenv bootcmd 'mmc read 0 0x50000000 0x800 0xA000; bootm 50000000'; setenv bootdelay 1; saveenv; re ``` -```sh -``` + diff --git "a/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260421151736921.png" "b/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260421151736921.png" index a253a56182cdc5115f2f2a98c1df318b14d5831f..a607c3f04d6095be2f4304d2de12c61642e4d207 100755 Binary files "a/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260421151736921.png" and "b/vendor/zsks/docs/clang/openharmony\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260421151736921.png" differ diff --git a/vendor/zsks/docs/clang/python/README.md b/vendor/zsks/docs/clang/python/README.md index b98734d2af216505dc8fe7be14556f9a524e4dd2..497faaa5ab7ae63d5c4e515af0de3d2b5497c367 100755 --- a/vendor/zsks/docs/clang/python/README.md +++ b/vendor/zsks/docs/clang/python/README.md @@ -28,13 +28,7 @@ cd Python-3.13.2 make -j$(nproc) && make altinstall ``` -![image-20251010143023136](pic/image-20251010143023136.png) -![image-20251010143136574](pic/image-20251010143136574.png) - -![image-20251010143226900](pic/image-20251010143226900.png) - -![image-20251010143640847](pic/image-20251010143640847.png) * **步骤2:**创建python环境,是python3.13.2生效 * 在服务器的命令行执行下面的命令,配置python环境变量 @@ -100,11 +94,7 @@ make LDFLAGS="--sysroot=/root/pegasus/os/OpenHarmony/out/hispark_aifly/ipcamera_ make install ``` -![image-20251009170325172](pic/image-20251009170325172.png) -![image-20251009171708407](pic/image-20251009171708407.png) - -![image-20251009171921919](pic/image-20251009171921919.png) ![image-20251009172007367](pic/image-20251009172007367.png) @@ -129,11 +119,7 @@ make CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin make install ``` -![image-20251009173438071](pic/image-20251009173438071.png) - -![image-20251009173659012](pic/image-20251009173659012.png) -![image-20251009174036856](pic/image-20251009174036856.png) ![image-20251009174105488](pic/image-20251009174105488.png) @@ -179,9 +165,7 @@ apt-get install automake libtool -y ./autogen.sh ``` -![image-20251009174843560](pic/image-20251009174843560.png) -![image-20251009174953996](pic/image-20251009174953996.png) * 修改 config.sub 文件中两处内容 @@ -205,10 +189,6 @@ apt-get install texinfo -y make && make install ``` -![image-20251009175706346](pic/image-20251009175706346.png) - -![image-20251009175825681](pic/image-20251009175825681.png) - ![image-20251009175854834](pic/image-20251009175854834.png) #### 5、libuuid的交叉编译 @@ -239,11 +219,7 @@ export CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/b make && make install ``` -![image-20251009180156789](pic/image-20251009180156789.png) -![image-20251009180424732](pic/image-20251009180424732.png) - -![image-20251009180446492](pic/image-20251009180446492.png) ![image-20251009180509397](pic/image-20251009180509397.png) @@ -269,12 +245,6 @@ export CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/b make && make install ``` -![image-20251009181033404](pic/image-20251009181033404.png) - -![image-20251009181219093](pic/image-20251009181219093.png) - -![image-20251009181250942](pic/image-20251009181250942.png) - ![image-20251009181318999](pic/image-20251009181318999.png) #### 7、readline的交叉编译 @@ -290,8 +260,6 @@ rm readline-8.2.tar.gz cd readline-8.2 ``` -![image-20251009191238117](pic/image-20251009191238117.png) - * 修改 support/config.sub 文件中一处内容 * 在1757行添加 | ohos* @@ -309,10 +277,6 @@ export CC="/root/pegasus/os/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/b make && make install ``` -![image-20251009195217103](pic/image-20251009195217103.png) - -![image-20251009191946638](pic/image-20251009191946638.png) - ![image-20251009200013989](pic/image-20251009200013989.png) ## 4、交叉编译python3.13.2 @@ -408,8 +372,6 @@ make -j"$(nproc)" 2>&1 | tee make.log.txt ![image-20251009202143477](pic/image-20251009202143477.png) -![image-20251009202450693](pic/image-20251009202450693.png) - ```sh make install 2>1 | tee install.log.txt ``` @@ -455,8 +417,6 @@ export PYTHONPATH=/mnt/install/lib/python3.13:$PYTHONPATH export LD_LIBRARY_PATH=/mnt/install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH ``` -image-20251010101732852 - ### 步骤3:运行python代码 * 如果第一次移植python3,需要给python3添加可执行权限才能运行 diff --git a/vendor/zsks/docs/clang/python/pic/image-20251009171921919.png b/vendor/zsks/docs/clang/python/pic/image-20251009171921919.png index 7896aea248c4b1f73eefa3fc963b2dee3780dc65..98bc5447335e7f8d87145ef7d95b54784bdaa7ab 100755 Binary files a/vendor/zsks/docs/clang/python/pic/image-20251009171921919.png and b/vendor/zsks/docs/clang/python/pic/image-20251009171921919.png differ diff --git a/vendor/zsks/docs/clang/python/pic/image-20251009200013989.png b/vendor/zsks/docs/clang/python/pic/image-20251009200013989.png index 1256aca756ed2b3604132215e1f12b37ce67cccc..02b07f9e5f0da6cbd0e6e707c2a942992319f68d 100755 Binary files a/vendor/zsks/docs/clang/python/pic/image-20251009200013989.png and b/vendor/zsks/docs/clang/python/pic/image-20251009200013989.png differ diff --git a/vendor/zsks/docs/clang/python/pic/image-20251009202143477.png b/vendor/zsks/docs/clang/python/pic/image-20251009202143477.png index 12d778905520fd6a1b734edf450d9977677c9c24..7477f6fc392c6beb9ffba2517032c061c60e1429 100755 Binary files a/vendor/zsks/docs/clang/python/pic/image-20251009202143477.png and b/vendor/zsks/docs/clang/python/pic/image-20251009202143477.png differ diff --git a/vendor/zsks/docs/clang/python/pic/image-20251009202450693.png b/vendor/zsks/docs/clang/python/pic/image-20251009202450693.png index 08e1430c7f30533da40714205d12fd88a075e23f..9bdd392bcf03705bef4473f2820d8c02c865d8fe 100755 Binary files a/vendor/zsks/docs/clang/python/pic/image-20251009202450693.png and b/vendor/zsks/docs/clang/python/pic/image-20251009202450693.png differ diff --git a/vendor/zsks/docs/clang/python/pic/image-20251010094441549.png b/vendor/zsks/docs/clang/python/pic/image-20251010094441549.png index e981001ec636db595d2766310bf95a49e58f3914..63e1eaef2664fcd548632148c151d55fb61a91f5 100755 Binary files a/vendor/zsks/docs/clang/python/pic/image-20251010094441549.png and b/vendor/zsks/docs/clang/python/pic/image-20251010094441549.png differ diff --git a/vendor/zsks/docs/gcc/alsa-lib/README.md b/vendor/zsks/docs/gcc/alsa-lib/README.md index 9b8c5902b48098bb6be0ad16c26a8ceeac4a8cb7..a316a6387c4377841bea4fb2799b96f49b374d8d 100755 --- a/vendor/zsks/docs/gcc/alsa-lib/README.md +++ b/vendor/zsks/docs/gcc/alsa-lib/README.md @@ -31,7 +31,7 @@ rm alsa-lib-1.1.7.tar.bz2 cd alsa-lib-1.1.7 ~~~ -![image-20260429152725139](./pic/image-20260429152725139.png) + ### 步骤2:配置环境变量 @@ -63,7 +63,7 @@ wget -O config.sub 'https://git.savannah.gnu.org/cgit/config.git/plain/config.su wget -O config.guess 'https://git.savannah.gnu.org/cgit/config.git/plain/config.guess' ~~~ -![image-20251017172745509](pic/image-20251017172745509.png) + * 如果源码包自带的 `config.sub/config.guess` 过旧导致 `--host` 识别失败,可用下面方式更新(可选) @@ -101,7 +101,7 @@ wget -O config.guess https://git.savannah.gnu.org/cgit/config.git/plain/config.g --build=x86_64-linux-gnu ~~~ -![image-20251017173155196](pic/image-20251017173155196.png) + ![image-20260429152829216](./pic/image-20260429152829216.png) @@ -119,10 +119,6 @@ make install 2>&1 | tee install_output.log **验证**:编译成功后,你应该能在 `$PWD/install` 目录下看到 `lib` 和 `include` 文件夹,其中包含 `libasound.so` 等文件。 -![image-20250904165253761](./pic/image-20250904165253761.png) - -![image-20250904165432734](./pic/image-20250904165432734.png) - ![image-20260429152915220](./pic/image-20260429152915220.png) ## 3.交叉编译alsa-util @@ -156,9 +152,7 @@ wget -O config.sub https://git.savannah.gnu.org/cgit/config.git/plain/config.sub wget -O config.guess https://git.savannah.gnu.org/cgit/config.git/plain/config.guess ~~~ -![image-20260430104449013](./pic/image-20260430104449013.png) -![image-20260430104453657](./pic/image-20260430104453657.png) ### **步骤 2:配置编译选项** @@ -309,8 +303,6 @@ export LD_LIBRARY_PATH=/mnt/alsa_install/lib:$LD_LIBRARY_PATH export ALSA_CONFIG_PATH=/mnt/alsa_install/share/alsa/alsa.conf:/mnt/alsa_install/share/alsa/cards/aliases.conf:/mnt/alsa_install/share/alsa/pcm/default.conf ~~~ -![image-20251020152649127](pic/image-20251020152649127.png) - ~~~bash chmod +x ./alsa_test ./alsa_test diff --git a/vendor/zsks/docs/gcc/ffmpeg/README.md b/vendor/zsks/docs/gcc/ffmpeg/README.md index ce5899d1481afdbf5a62118c672836d982bdaa58..61acce44a3890eb605e157240bc3163d21391d6d 100755 --- a/vendor/zsks/docs/gcc/ffmpeg/README.md +++ b/vendor/zsks/docs/gcc/ffmpeg/README.md @@ -1,1294 +1,1290 @@ -# FFmpeg移植 - -## 1、软硬件环境 - -* 开发板:海鸥派 -* 交叉编译工具链:openEuler aarch64 GCC(`aarch64-openeuler-linux-gnu-gcc`) - -* 编译链路径:`/root/openeuler_gcc_arm64le/bin` (根据实际修改) -* Python版本:Python-3.13.2 -* 移植的ffmpeg版本:FFmpeg-6.0 - -## 2、安装依赖 - -* 由于在编译ffmpeg的时候,需要依赖其他第三方软件,因此在编译ffmpeg之前,我们先把它依赖的第三方软件全部交叉编译出来。 - -### 步骤1:交叉编译v4l2 - -* 可以参考[v4l2的移植文档](../libv4l2/README.md)的前两章节,完成v4l2的移植工作。 - -### 步骤2:交叉编译x264 - -* 在服务器的命令行执行下面的命令,下载源码,配置编译链 - -```sh -cd /root/pegasus/vendor/opensource/ -git clone https://code.videolan.org/videolan/x264.git -cd x264 - - - wget -O config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' - wget -O config.sub 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' - -TOOLCHAIN_BIN="/root/openeuler_gcc_arm64le/bin" -CROSS_PREFIX="aarch64-openeuler-linux-gnu" -SYSROOT="$(${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --print-sysroot 2>/dev/null || true)" -SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" - -CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" \ -CXX="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++ --sysroot=${SYSROOT}" \ -CFLAGS="-march=armv8-a" \ -./configure \ - --host=aarch64-openeuler-linux-gnu \ - --prefix=$(pwd)/install \ - --enable-shared \ - --disable-cli - -make -j$(nproc) && make install -``` - -![image-20260429165209703](./pic/image-20260429165209703.png) - -* 编译成功后会在install目录下生成如下文件 - -![image-20260429165227713](./pic/image-20260429165227713.png) - -### 步骤3:交叉编译x265 - -* 在服务器的命令行执行下面的命令,下载源码 - -```sh -cd ../ -wget https://bitbucket.org/multicoreware/x265_git/downloads/x265_3.5.tar.gz - -#如果下载不成功尝试: -#打开浏览器访问:https://mirrors.tuna.tsinghua.edu.cn/debian/pool/main/x/x265/ -#找到文件 x265_3.5.orig.tar.gz -#下载到本地电脑。 - -tar xf x265_3.5.tar.gz -cd x265_3.5 -``` - -* 将下面内容添加到 build/aarch64-linux/crosscompile.cmake文件中 -* 注意:里面的库、头文件等的绝对路径请根据自己服务器的实际情况进行修改。 - -```sh -# crosscompile.cmake for x265 (openEuler GCC aarch64) -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR aarch64) - -# ====== 你的工具链路径(按实际修改)====== -set(TOOLCHAIN_BIN "/root/openeuler_gcc_arm64le/bin") -set(CROSS_PREFIX "aarch64-openeuler-linux-gnu") - -# ====== 你的 sysroot(按实际修改)====== -set(CMAKE_SYSROOT "/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot") - -# compilers -set(CMAKE_C_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc") -set(CMAKE_CXX_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++") -set(CMAKE_ASM_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc") - -# binutils -set(CMAKE_AR "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar") -set(CMAKE_RANLIB "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ranlib") -set(CMAKE_STRIP "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip") -set(CMAKE_NM "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-nm") -set(CMAKE_LINKER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ld") - -# ====== 关键:只在目标根路径里找库/头文件,避免混入宿主机 ====== -set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}") -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -# ====== flags(保证 PIC + 明确 sysroot)====== -set(CMAKE_C_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC -march=armv8-a") -set(CMAKE_CXX_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC -march=armv8-a") -set(CMAKE_ASM_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC") - -set(CMAKE_EXE_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}") -set(CMAKE_SHARED_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}") - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -# (可选)如果你担心复用缓存导致误用宿主机编译器,可以打开这句强制: -# set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -``` - -![image-20260429165324954](./pic/image-20260429165324954.png) - - - -```sh -cd /root/pegasus/vendor/opensource/x265_3.5 - -mkdir build-aarch64 && cd build-aarch64 - -cmake ../source \ - -G "Unix Makefiles" \ - -DCMAKE_TOOLCHAIN_FILE=../build/aarch64-linux/crosscompile.cmake \ - -DCMAKE_INSTALL_PREFIX=/root/pegasus/vendor/opensource/x265_3.5/install \ - -DENABLE_SHARED=ON \ - -DENABLE_PIC=ON \ - -DENABLE_ASSEMBLY=OFF \ - -Wno-dev - -make -j"$(nproc)" && make install -``` - -![image-20260429165401463](./pic/image-20260429165401463.png) - -![image-20260429165426965](./pic/image-20260429165426965.png) - - - -* 编译完成后,会在install目录下生成如下文件 - -![image-20260429165455413](./pic/image-20260429165455413.png) - -## 3、交叉编译FFmpeg - -### 步骤1:下载源码 - -* 在服务器的命令行执行下面的命令,下载ffmpeg源码 - -```sh -cd ../ - -git clone -b release/6.0 https://gitee.com/zhongshankuangshi/ffmpeg.git - -cd ffmpeg -``` - -![image-20251021205649485](pic/image-20251021205649485.png) - -### 步骤2:环境变量配置 - -* 注意这里出现的决定路径的地址,请根据自己服务器的具体情况进行修改。 - -```sh -# 1. 设置工具链路径 -export TOOLCHAIN_BIN="/root/openeuler_gcc_arm64le/bin" -export CROSS_PREFIX="aarch64-openeuler-linux-gnu" -export SYSROOT="$(${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --print-sysroot 2>/dev/null || true)" -SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" - -export CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc" -export CXX="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++" -export AR="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar" -export LD="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ld" -export RANLIB="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ranlib" -export STRIP="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip" - -# 2. 设置依赖库路径 (请确保这些路径下的 lib 目录中存在 .so 或 .a 文件) -export X264_LIB="/root/pegasus/vendor/opensource/x264/install" -export X265_LIB="/root/pegasus/vendor/opensource/x265_3.5/install" -export V4L2_LIB="/root/pegasus/vendor/opensource/v4l-utils/install" - -# 3. 导出 PKG_CONFIG_PATH -export PKG_CONFIG_PATH="${X264_LIB}/lib/pkgconfig:${X265_LIB}/lib/pkgconfig:${V4L2_LIB}/lib/pkgconfig:$PKG_CONFIG_PATH" - -# 4. 导出 CFLAGS 和 LDFLAGS -export CFLAGS="-I${X264_LIB}/include -I${X265_LIB}/include -I${V4L2_LIB}/include --sysroot=${SYSROOT}" -export LDFLAGS="-L${X264_LIB}/lib -L${X265_LIB}/lib -L${V4L2_LIB}/lib --sysroot=${SYSROOT}" -``` - -![image-20260429165518866](./pic/image-20260429165518866.png) - -### 步骤3:修改相关编译脚本 - -* 在pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common/Makefile的第4行,添加一个fPIC选项到CFLAGS,如下图所示: - -![image-20251022142837408](pic/image-20251022142837408.png) - -* 然后进入到pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common目录下,执行 make clean && make 命令,重新生成.o文件 -* 注意:请根据自己服务器的实际情况修改里面的绝对路径 - -```sh -cd /root/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common -make clean && make -``` - -![image-20260429165603344](./pic/image-20260429165603344.png) - -* 在ffmpeg目录下创建一个build_ffmpeg.sh脚本,把下面的内容复制进去 - -* 注意:请根据自己服务器的实际情况修改里面的绝对路径 - -![image-20251022150910879](pic/image-20251022150910879.png) - -```sh -#!/usr/bin/env bash -set -euo pipefail - -############################################# -# FFmpeg 交叉编译脚本(按 docs/gcc/ffmpeg/README.md 整理) -# - 生成 ./hisi_sdk_lib/libhisi_sdk_init.so -# - 配置并运行 FFmpeg ./configure -# -# 说明: -# - 你可以通过环境变量覆盖下面的路径(例如:X265_PATH=... ./build_ffmpeg.sh) -# - 本脚本会自动检测 pkg-config 是否能找到 x265;找不到则自动禁用 --enable-libx265 -############################################# - -msg() { printf '%s\n' "$*"; } -die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } - -VERBOSE="${VERBOSE:-0}" # 默认 0:减少输出;设为 1 显示详细信息 - -vmsg() { - [[ "${VERBOSE}" == "1" ]] && msg "$@" -} - -warn() { - # 统一 WARNING 输出,便于后续做收敛 - msg "WARNING: $*" -} - -require_cmd() { - command -v "$1" >/dev/null 2>&1 || die "找不到命令:$1" -} - -pkg_has() { - local name="$1" - pkg-config --exists "$name" >/dev/null 2>&1 -} - -pkg_cflags() { - local name="$1" - pkg-config --cflags "$name" 2>/dev/null || true -} - -pkg_libs() { - local name="$1" - pkg-config --libs "$name" 2>/dev/null || true -} - -can_link_x265() { - # 返回 0 表示“真的能用 x265 编译+链接” - # 这比单纯 pkg-config --exists 更可信,能覆盖: - # - x265.pc 存在但路径错 - # - 只装了 pc 没装库/头文件 - # - pc 输出的 -L/-l 组合无法在交叉编译 sysroot 下链接 - # - # 注意:x265 本质是 C++ 实现(即便提供 C API 头文件), - # 仅用 $CC 链接经常会因为缺少 libstdc++ 等依赖而失败; - # 而 pkg-config 的 --libs 也不一定会把 -lstdc++ 带出来。 - # 所以这里用 $CXX 做最终链接,并补齐常见依赖。 - local tmpd - tmpd="$(mktemp -d)" - trap 'rm -rf "$tmpd"' RETURN - - local cflags libs - cflags="$(pkg_cflags x265)" - libs="$(pkg_libs x265)" - - if [[ -z "$cflags" || -z "$libs" ]]; then - return 1 - fi - - cat >"${tmpd}/conftest.cpp" <<'EOF' -#include -int main(void) { - x265_param p; - x265_param_default(&p); - return 0; -} -EOF - - # 注意:这里要用交叉编译器做真正的链接测试 - # 额外补齐常见的 C++ 运行库依赖(避免误判)。 - if ! "$CXX" --sysroot="${SYSROOT}" -o "${tmpd}/conftest" "${tmpd}/conftest.cpp" ${cflags} ${libs} -lstdc++ -lm -lpthread -ldl >/dev/null 2>&1; then - return 1 - fi - - return 0 -} - -add_pkg_dir_if_exists() { - local d="$1" - [[ -d "$d" ]] || return 0 - if [[ -z "${_PKG_DIRS:-}" ]]; then - _PKG_DIRS="$d" - else - _PKG_DIRS="${_PKG_DIRS}:$d" - fi -} - -setup_pkg_config_env() { - # 交叉编译时,尽量避免 pkg-config 混入宿主机默认路径。 - # - # 重要:PKG_CONFIG_SYSROOT_DIR 的行为是“把 .pc 里的前缀路径整体加上 sysroot”。 - # 如果你的三方库(x264/x265/v4l2)安装在 sysroot 外(例如 /root/pegasus/vendor/opensource/...), - # 那么启用 PKG_CONFIG_SYSROOT_DIR 会把路径变成: - # ${SYSROOT}/root/pegasus/vendor/opensource/... - # 从而导致找不到头文件/库,出现“pkg-config 能找到,但链接失败”的情况。 - # - # 因此这里做一个智能判定:只有当三方库前缀本身就在 SYSROOT 之下时,才启用 PKG_CONFIG_SYSROOT_DIR; - # 否则默认不设置(用户仍可通过环境变量强制设置)。 - - is_under_sysroot() { - local p="$1" - [[ -n "${SYSROOT:-}" ]] || return 1 - [[ "$p" == "${SYSROOT%/}/"* ]] - } - - local want_sysroot=0 - if [[ -n "${PKG_CONFIG_SYSROOT_DIR:-}" ]]; then - # 用户显式设置就尊重 - want_sysroot=1 - else - if is_under_sysroot "$X264_PATH" || is_under_sysroot "$X265_PATH" || is_under_sysroot "$V4L2_PATH"; then - want_sysroot=1 - fi - fi - - if [[ "$want_sysroot" == "1" ]]; then - export PKG_CONFIG_SYSROOT_DIR="${PKG_CONFIG_SYSROOT_DIR:-$SYSROOT}" - else - unset PKG_CONFIG_SYSROOT_DIR || true - fi - - _PKG_DIRS="" - - # 常见安装布局:lib/pkgconfig、lib64/pkgconfig、share/pkgconfig - add_pkg_dir_if_exists "${X264_PATH}/lib/pkgconfig" - add_pkg_dir_if_exists "${X264_PATH}/lib64/pkgconfig" - add_pkg_dir_if_exists "${X264_PATH}/share/pkgconfig" - - add_pkg_dir_if_exists "${X265_PATH}/lib/pkgconfig" - add_pkg_dir_if_exists "${X265_PATH}/lib64/pkgconfig" - add_pkg_dir_if_exists "${X265_PATH}/share/pkgconfig" - - add_pkg_dir_if_exists "${V4L2_PATH}/lib/pkgconfig" - add_pkg_dir_if_exists "${V4L2_PATH}/lib64/pkgconfig" - add_pkg_dir_if_exists "${V4L2_PATH}/share/pkgconfig" - - # 允许外部追加(但不要让它抢占我们的交叉编译路径) - if [[ -n "${PKG_CONFIG_PATH:-}" ]]; then - export PKG_CONFIG_PATH="${_PKG_DIRS}:${PKG_CONFIG_PATH}" - else - export PKG_CONFIG_PATH="${_PKG_DIRS}" - fi - - # 覆盖默认搜索目录,避免 /usr/lib/pkgconfig 等宿主路径影响检测 - export PKG_CONFIG_LIBDIR="${_PKG_DIRS}${PKG_CONFIG_LIBDIR:+:${PKG_CONFIG_LIBDIR}}" -} - -pc_file_hint() { - local prefix="$1" - local name="$2" - local cands=( - "${prefix}/lib/pkgconfig/${name}.pc" - "${prefix}/lib64/pkgconfig/${name}.pc" - "${prefix}/share/pkgconfig/${name}.pc" - ) - local c - for c in "${cands[@]}"; do - if [[ -f "$c" ]]; then - printf '%s' "$c" - return 0 - fi - done - # fallback:返回最常见的那个 - printf '%s' "${cands[0]}" - return 0 -} - -abspath() { - local p="$1" - if [[ "$p" == /* ]]; then - printf '%s' "$p" - else - printf '%s/%s' "$(pwd)" "$p" - fi -} - -# --- 1) 路径配置(可通过环境变量覆盖) --- -TOOLCHAIN_BIN="${TOOLCHAIN_BIN:-/root/openeuler_gcc_arm64le/bin}" -CROSS_PREFIX="${CROSS_PREFIX:-aarch64-openeuler-linux-gnu}" -SYSROOT="${SYSROOT:-$("${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc" --print-sysroot 2>/dev/null || true)}" -SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" - -HISI_SDK_BASE="${HISI_SDK_BASE:-/root/pegasus/platform/ss928v100_gcc/smp/a55_linux}" -HISI_MPP_BASE="${HISI_MPP_BASE:-${HISI_SDK_BASE}/mpp}" -HISI_COMMON_DIR="${HISI_COMMON_DIR:-${HISI_SDK_BASE}/mpp/sample/common}" - -X264_PATH="${X264_PATH:-/root/pegasus/vendor/opensource/x264/install}" -X265_PATH="${X265_PATH:-/root/pegasus/vendor/opensource/x265_3.5/install}" -V4L2_PATH="${V4L2_PATH:-/root/pegasus/vendor/opensource/v4l-utils/install}" - -FF_PREFIX="${FF_PREFIX:-$(abspath ./install)}" -SDK_LIB_DIR="${SDK_LIB_DIR:-$(abspath ./hisi_sdk_lib)}" - -# --- 2) 工具链变量 --- -export CC="${CC:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc}" -export CXX="${CXX:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++}" -export AR="${AR:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar}" -export STRIP="${STRIP:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip}" - -require_cmd "$CC" -require_cmd "$CXX" -require_cmd "$AR" -require_cmd "$STRIP" -require_cmd pkg-config - -mkdir -p "$SDK_LIB_DIR" - -# --- 3) 构建 Hisi SDK 辅助库 --- -LINK_LIBS="-lss_mpi -lot_osal -lot_irq -lot_sys -lsecurec -lpthread -lm -lstdc++ -ldl -lrt" - -msg ">>> 正在构建 libhisi_sdk_init.so ..." -"$CC" -shared -fPIC --sysroot="${SYSROOT}" \ - -o "${SDK_LIB_DIR}/libhisi_sdk_init.so" \ - "${HISI_COMMON_DIR}/sdk_init.o" "${HISI_COMMON_DIR}/sdk_exit.o" \ - -L"${HISI_MPP_BASE}/out/lib" \ - ${LINK_LIBS} \ - -Wl,--allow-shlib-undefined - -msg "✓ libhisi_sdk_init.so 创建成功" - -# --- 4) pkg-config / include / lib 路径 --- -setup_pkg_config_env -EXTRA_CFLAGS="-fPIC -I${HISI_COMMON_DIR} -I${HISI_MPP_BASE}/include -I${HISI_SDK_BASE}/mpp/out/include --sysroot=${SYSROOT}" - -# 运行时依赖库白名单(参考 OpenHarmony/clang README 的 allowlist 思路) -# 背景: -# - 海思/MPP 的部分 .so 可能 DT_NEEDED 不完整,导致运行时出现: -# - /usr/lib64/libss_mpi.so: undefined symbol: voice_decode_frame -# - /usr/lib64/libot_sys.so: undefined symbol: cmpi_stop_modules -# - 解决思路:让最终 ffmpeg 可执行文件显式依赖一组“可能提供符号/初始化模块”的库, -# 并通过 --no-as-needed 强制写入 DT_NEEDED。 -# -# 可通过环境变量覆盖(建议按需裁剪,先全量保证能跑): -# HISI_RUNTIME_LIBS="-lot_sys -lot_osal -lss_mpi ..." -# -# 默认:尽量对齐 OpenHarmony 脚本 allowlist(偏全量,便于先跑通) -HISI_RUNTIME_LIBS_DEFAULT=( - -lsecurec - -lot_base - -lot_osal - -lot_sys - -lot_chnl - -lot_rgn - -lot_gdc - -lot_vgs - -lot_dis - -lot_vpp - -lot_vi - -lot_isp - -lot_vpss - -lot_vo - -lot_vedu - -lot_rc - -lot_venc - -lot_h264e - -lot_h265e - -lot_jpege - -lot_jpegd - -lot_vfmw - -lot_vdec - -lot_irq - -lot_mpi_isp - -lss_ive - -lss_dpu_rect - -lss_dpu_match - -lss_mau - -lsvp_acl - -lot_aio - -lot_ai - -lot_ao - -lot_aenc - -lot_adec - -lot_acodec - -lot_pwm - -lot_piris - -lss_mpi - -lss_hdmi - -lss_isp - -lss_ae - -lss_awb - -lss_voice_engine - -lss_calcflicker - -lot_sensor_i2c - -lss_extend_stats - -lss_ir_auto - -lss_bnr - -lss_acs - -lss_drc - -lss_dehaze - -lss_ldci - -lss_crb - -lprotobuf-c - -lss_upvqe - -lss_dnvqe -) - -# 关键:libss_mpi.so 未在 DT_NEEDED 中声明 libss_voice_engine,但依赖 voice_decode_frame; -# 该符号由 libss_voice_engine.so 提供,必须进入最终 ffmpeg 的 NEEDED,否则板端 symbol lookup 失败。 -HISI_RUNTIME_LIBS_ESSENTIAL=( - -lss_voice_engine -) - -library_exists_in_dirs() { - # $1: libname without "lib" prefix, e.g. "ot_sys" for -lot_sys - local name="${1:-}" - shift || true - [[ -n "$name" ]] || return 1 - local d - for d in "$@"; do - [[ -d "$d" ]] || continue - if [[ -f "$d/lib${name}.so" || -f "$d/lib${name}.so.0" || -f "$d/lib${name}.a" ]]; then - return 0 - fi - # 兼容带版本号的 so - if compgen -G "$d/lib${name}.so.*" >/dev/null 2>&1; then - return 0 - fi - done - return 1 -} - -filter_existing_link_flags() { - # 输入:一组 "-lxxx" flags - # 输出:只保留在给定 lib dirs 中能找到的 flags - local -a in_flags=("$@") - local -a out_flags=() - local -a missing_flags=() - local f name - for f in "${in_flags[@]}"; do - if [[ "$f" =~ ^-l(.+)$ ]]; then - name="${BASH_REMATCH[1]}" - if library_exists_in_dirs "$name" "${HISI_LIB_DIRS[@]}"; then - out_flags+=("$f") - else - missing_flags+=("$f") - fi - else - out_flags+=("$f") - fi - done - - if (( ${#missing_flags[@]} > 0 )); then - if [[ "${VERBOSE}" == "1" ]]; then - local mf - for mf in "${missing_flags[@]}"; do - warn "跳过不存在的库依赖:${mf}(在 ${HISI_LIB_DIRS[*]} 未找到对应的 lib*.so/.a)" - done - else - warn "有 ${#missing_flags[@]} 个 allowlist 库在 out/lib 中不存在,已自动跳过(如需列表:VERBOSE=1)" - fi - fi - printf '%s ' "${out_flags[@]}" -} - -if [[ -n "${HISI_RUNTIME_LIBS:-}" ]]; then - # shellcheck disable=SC2206 - HISI_RUNTIME_LIBS_ARR=( ${HISI_RUNTIME_LIBS} ) -else - HISI_RUNTIME_LIBS_ARR=( "${HISI_RUNTIME_LIBS_DEFAULT[@]}" ) -fi - -# Hisilicon/MPP 库目录(用于过滤 allowlist,避免 configure 链接测试直接失败) -HISI_LIB_DIRS=( - "${HISI_MPP_BASE}/out/lib" - "${HISI_MPP_BASE}/out/lib/svp_npu" - "${SDK_LIB_DIR}" -) - -# 必需库优先加入再过滤;若 SDK 中缺失则立刻失败,避免静默跳过导致 DT_NEEDED 不完整 -for _ess in "${HISI_RUNTIME_LIBS_ESSENTIAL[@]}"; do - if [[ "$_ess" =~ ^-l(.+)$ ]]; then - _n="${BASH_REMATCH[1]}" - if ! library_exists_in_dirs "$_n" "${HISI_LIB_DIRS[@]}"; then - die "缺少必需运行库:lib${_n}.so(${_ess}),无法链接 voice_decode_frame 等符号。请检查 HISI_MPP_BASE=${HISI_MPP_BASE}" - fi - fi -done - -# rpath:优先使用安装目录相对路径,其次允许你覆盖为板端系统目录 -# 默认增加 svp_npu(OpenHarmony README 也会把它加入 LD_LIBRARY_PATH) -TARGET_RPATH_DIR="${TARGET_RPATH_DIR:-\$ORIGIN/../lib}" -TARGET_RPATH_NPU_DIR="${TARGET_RPATH_NPU_DIR:-\$ORIGIN/../lib/svp_npu}" -RPATH_FLAGS=( - "-Wl,-rpath,${TARGET_RPATH_DIR}" - "-Wl,-rpath,${TARGET_RPATH_NPU_DIR}" - "-Wl,--enable-new-dtags" -) - -# 合并 essential + 用户/默认列表后再过滤(essential 已校验存在) -HISI_RUNTIME_LIBS_MERGED=( "${HISI_RUNTIME_LIBS_ESSENTIAL[@]}" "${HISI_RUNTIME_LIBS_ARR[@]}" ) -HISI_RUNTIME_LIBS_FILTERED="$(filter_existing_link_flags "${HISI_RUNTIME_LIBS_MERGED[@]}")" - -if [[ -z "${HISI_RUNTIME_LIBS_FILTERED// /}" ]]; then - die "HISI_RUNTIME_LIBS_FILTERED 为空(运行库 allowlist 全部被跳过)。请检查 HISI_MPP_BASE/out/lib 是否齐全。" -fi - -EXTRA_LDFLAGS="-fPIC -L${SDK_LIB_DIR} -L${HISI_MPP_BASE}/out/lib -lhisi_sdk_init \ - -L${HISI_MPP_BASE}/out/lib/svp_npu \ - -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed \ - ${RPATH_FLAGS[*]} \ - ${LINK_LIBS}" - -# --- 5) 自动处理 x265 not found using pkg-config --- -ENABLE_X265=1 -if ! pkg_has x265; then - ENABLE_X265=0 - msg "========================================" - msg "WARNING: pkg-config 找不到 x265,将自动禁用 --enable-libx265" - msg "- 期望的 .pc 路径:$(pc_file_hint "${X265_PATH}" x265)" - msg "- 当前 PKG_CONFIG_PATH:${PKG_CONFIG_PATH:-}" - msg "- 当前 PKG_CONFIG_LIBDIR:${PKG_CONFIG_LIBDIR:-}" - msg "- 当前 PKG_CONFIG_SYSROOT_DIR:${PKG_CONFIG_SYSROOT_DIR:-}" - msg "- 调试命令:pkg-config --print-errors --cflags --libs x265" - msg "如果你确认 x265 已安装,请检查 X265_PATH 是否指向正确 install 目录。" - msg "========================================" -else - # pkg-config 能找到不代表能链接,额外做一次真实的编译/链接探测 - if ! can_link_x265; then - ENABLE_X265=0 - msg "========================================" - msg "WARNING: pkg-config 能找到 x265,但交叉编译器无法用其输出完成链接,将自动禁用 --enable-libx265" - msg "- x265.pc:$(pc_file_hint "${X265_PATH}" x265)" - msg "- pkg-config --cflags x265:$(pkg_cflags x265)" - msg "- pkg-config --libs x265:$(pkg_libs x265)" - msg "- 建议你在服务器手动跑:" - msg " pkg-config --print-errors --cflags --libs x265" - msg " 并确认对应的 lib 目录下确实有 libx265.so / libx265.a" - msg "========================================" - fi -fi - -# x264 / v4l2 也做一下快速提示(缺了通常也会 configure 失败) -if ! pkg_has x264; then - msg "WARNING: pkg-config 找不到 x264(后续可能 configure 失败)。期望:$(pc_file_hint "${X264_PATH}" x264)" -fi -if ! pkg_has libv4l2; then - msg "WARNING: pkg-config 找不到 libv4l2(后续可能 configure 失败)。期望:$(pc_file_hint "${V4L2_PATH}" libv4l2)" -fi - -# --- 6) 准备 FFmpeg 编译参数 --- -CONFIGURE_ARGS=( - --prefix="${FF_PREFIX}" - --arch=aarch64 - --target-os=linux - --enable-cross-compile - --cc="${CC}" - --cxx="${CXX}" - --ar="${AR}" - --strip="${STRIP}" - --sysroot="${SYSROOT}" - --pkg-config="pkg-config" - --enable-gpl - --enable-libx264 - --enable-libv4l2 - --enable-encoder=h264_ss928,h265_ss928,mjpeg_ss928 - --enable-decoder=h264_ss928,h265_ss928,mjpeg_ss928 - --extra-cflags="${EXTRA_CFLAGS}" - --extra-ldflags="${EXTRA_LDFLAGS}" - --extra-ldexeflags="-Wl,--allow-shlib-undefined -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed ${RPATH_FLAGS[*]}" - --disable-static - --enable-shared -) - -if [[ "${ENABLE_X265}" == "1" ]]; then - CONFIGURE_ARGS+=( --enable-libx265 ) -fi - -msg "========================================" -msg "开始配置 FFmpeg..." -msg "========================================" - -print_config_log_tail() { - local log="ffbuild/config.log" - [[ -f "$log" ]] || return 0 - msg "" - msg "-------- ffbuild/config.log (last 120 lines) --------" - if command -v tail >/dev/null 2>&1; then - tail -n 120 "$log" 2>/dev/null || true - else - # fallback - sed -n '1h;1!H;${g;s/.*\\(\n.*\\)\\{120\\}/\\1/;p;}' "$log" 2>/dev/null || true - fi - msg "-----------------------------------------------------" -} - -print_compiler_test_errors() { - # 从 config.log 中尽量抽取“编译器自测失败”的真实报错行 - local log="ffbuild/config.log" - [[ -f "$log" ]] || return 0 - msg "" - msg "-------- compiler test related errors (grep) --------" - # 只抓高信号关键字,避免刷屏 - grep -nE "unable to create an executable file|C compiler test failed|collect2:|ld(\.bfd)?:|skipping incompatible|cannot find|crt1\.o|crti\.o|crtn\.o|libgcc|libc\.so" "$log" 2>/dev/null | tail -n 120 || true - msg "-----------------------------------------------------" -} - -run_configure() { - # 默认把 configure 输出收敛到日志文件,避免刷屏;失败时再摘出来 - local log="${CONFIGURE_LOG:-./ffbuild_configure.log}" - if [[ "${VERBOSE}" == "1" ]]; then - vmsg "configure 命令:./configure $*" - ./configure "$@" || return 1 - else - ./configure "$@" >"$log" 2>&1 || return 1 - fi - return 0 -} - -# 重要策略(已被你的日志验证): -# - 带一大串 HISI_RUNTIME_LIBS/--no-as-needed/rpath 的链接参数会让 configure 的“编译器自测”失败 -# - 但这些库又确实是板端运行时解 undefined symbol 必需的 -# 因此: -# 1) configure 阶段使用最小 ldflags 通过自测 -# 2) configure 成功后,再把 runtime libs / rpath 注入 ffbuild/config.mak(影响最终可执行文件链接) -CONFIGURE_ARGS_MIN=( - --prefix="${FF_PREFIX}" - --arch=aarch64 - --target-os=linux - --enable-cross-compile - --cc="${CC}" - --cxx="${CXX}" - --ar="${AR}" - --strip="${STRIP}" - --sysroot="${SYSROOT}" - --pkg-config="pkg-config" - --enable-gpl - --enable-libx264 - --enable-libv4l2 - --enable-encoder=h264_ss928,h265_ss928,mjpeg_ss928 - --enable-decoder=h264_ss928,h265_ss928,mjpeg_ss928 - --extra-cflags="${EXTRA_CFLAGS}" - # configure 阶段:只保留最基础的 ldflags(避免 allowlist/rpath 影响编译器自测) - --extra-ldflags="-fPIC -L${SDK_LIB_DIR} -L${HISI_MPP_BASE}/out/lib -L${HISI_MPP_BASE}/out/lib/svp_npu -lhisi_sdk_init ${LINK_LIBS}" - --extra-ldexeflags="-Wl,--allow-shlib-undefined" - --disable-static - --enable-shared -) -if [[ "${ENABLE_X265}" == "1" ]]; then - CONFIGURE_ARGS_MIN+=( --enable-libx265 ) -fi - -if ! run_configure "${CONFIGURE_ARGS_MIN[@]}"; then - msg "" - msg "❌ 配置失败。" - if [[ "${VERBOSE}" != "1" ]]; then - msg "提示:已将 configure 输出写入 ${CONFIGURE_LOG:-./ffbuild_configure.log}" - fi - msg "下面打印 config.log 末尾以便定位:" - print_config_log_tail - print_compiler_test_errors - - exit 1 -fi - -msg "" -msg "✅ 配置成功!将替换 ffbuild/config.mak 中的 LDEXEFLAGS(避免板端 undefined symbol)" - -patch_ffbuild_ldexeflags_line() { - # 旧实现使用文件末尾 LDEXEFLAGS+=,曾出现未参与最终链接的情况;改为直接改写唯一的 - # “LDEXEFLAGS= ...” 行,确保 ffmpeg/ffprobe 等可执行文件链接参数完整。 - local mk="ffbuild/config.mak" - [[ -f "$mk" ]] || die "找不到 ${mk}(configure 未成功生成)" - - # 删除旧版本脚本追加在文件末尾的注释 + LDEXEFLAGS+= 块(若存在) - if grep -q '^# HISI_RUNTIME_LIBS_INJECTED=1$' "$mk" 2>/dev/null; then - awk ' - /^# HISI_RUNTIME_LIBS_INJECTED=1$/ { skip = 1; next } - skip && /^LDEXEFLAGS\+=/ { skip = 0; next } - skip { next } - { print } - ' "$mk" >"${mk}.strip" && mv "${mk}.strip" "$mk" - fi - - local rf rf_make rpath_tail="" - for rf in "${RPATH_FLAGS[@]}"; do - rf_make="$(printf '%s' "$rf" | sed 's/\$/$$/g')" - rpath_tail+=" ${rf_make}" - done - - local new_line - new_line="LDEXEFLAGS= -Wl,--allow-shlib-undefined -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed${rpath_tail}" - - local replaced=0 - while IFS= read -r line || [[ -n "$line" ]]; do - if [[ "$line" == LDEXEFLAGS=* ]]; then - printf '%s\n' "$new_line" - replaced=1 - continue - fi - printf '%s\n' "$line" - done <"$mk" >"${mk}.new" - - if [[ "$replaced" != 1 ]]; then - rm -f "${mk}.new" - die "未在 ${mk} 中找到 LDEXEFLAGS= 行(可能 configure 输出格式变化),无法写入 Hisi 运行库链接参数" - fi - mv "${mk}.new" "$mk" - - msg "✓ 已替换 ${mk} 中的 LDEXEFLAGS(含 -lss_voice_engine 等,用于补齐 libss_mpi 未声明的 DT_NEEDED)" - vmsg ">>> 新 LDEXEFLAGS 预览(截断显示):${new_line:0:220}..." -} - -patch_ffbuild_ldexeflags_line - -msg "接下来请重新完整链接:make clean && make -j\$(nproc) && make install" -msg "(若仅增量 make,可能仍使用旧的 ffmpeg 链接结果;至少执行:rm -f ffmpeg_g fftools/ffmpeg_g && make -j\$(nproc))" -``` - -### 步骤4:编译ffmpeg - -* 在服务器的命令行,执行下面的命令,进行编译ffmpeg前的配置 - -```sh -chmod +x build_ffmpeg.sh - -./build_ffmpeg.sh -``` - -![image-20260429165631483](./pic/image-20260429165631483.png) - -* 在服务器的命令行,执行下面的命令,进行ffmpeg的编译 - -```sh -make -j$(nproc) && make install -``` - -![image-20260429165648074](./pic/image-20260429165648074.png) - -* 编译完成之后,会在install目录下生成下面的内容 -* 并且在ffmpeg目录下生成一个hisi_sdk_lib的文件夹,里面有一个libhisi_sdk_init.so库 - -![image-20260429165656879](./pic/image-20260429165656879.png) - -![image-20251022151540301](pic/image-20251022151540301.png) - -### 步骤5:编译sample - -* 在服务器的命令行,执行下面的命令,分别编译ffmpeg和hisi目录下的编解码案例 - -```sh -cd sample/ffmpeg -``` - -将Makefile替换成下面的(注意路径替换正确) - -~~~bash -# 1. 根目录改为你的真实用户目录 -ROOT_DIR := /root - -# 2. 编译器改为 GCC(利用你配置好的 PATH 环境变量) -CXX := aarch64-openeuler-linux-gnu-g++ - -# 3. 头文件路径(指向 GCC 版本的 SDK) -INCLUDES := \ - -I${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/include \ - -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/include \ - -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common - -# 4. 库路径(指向 GCC 版本的库) -LIB_PATHS := \ - -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/hisi_sdk_lib \ - -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ - -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib \ - -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/svp_npu \ - -L${ROOT_DIR}/pegasus/vendor/opensource/x264/install/lib - -# 5. 链接选项(与海思 build_ffmpeg.sh 中 HISI_RUNTIME_LIBS_DEFAULT 对齐;须整块放在 --no-as-needed 内写入 DT_NEEDED) -LDFLAGS := \ - -Wl,-rpath,${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ - -Wl,--allow-shlib-undefined \ - -Wl,--no-as-needed \ - -lhisi_sdk_init \ - -lsecurec \ - -lot_base \ - -lot_osal \ - -lot_sys \ - -lot_chnl \ - -lot_rgn \ - -lot_gdc \ - -lot_vgs \ - -lot_dis \ - -lot_vpp \ - -lot_vi \ - -lot_isp \ - -lot_vpss \ - -lot_vo \ - -lot_vedu \ - -lot_rc \ - -lot_venc \ - -lot_h264e \ - -lot_h265e \ - -lot_jpege \ - -lot_jpegd \ - -lot_vfmw \ - -lot_vdec \ - -lot_irq \ - -lot_mpi_isp \ - -lss_ive \ - -lss_dpu_rect \ - -lss_dpu_match \ - -lss_mau \ - -lsvp_acl \ - -lot_aio \ - -lot_ai \ - -lot_ao \ - -lot_aenc \ - -lot_adec \ - -lot_acodec \ - -lot_pwm \ - -lot_piris \ - -lss_mpi \ - -lss_hdmi \ - -lss_isp \ - -lss_ae \ - -lss_awb \ - -lss_voice_engine \ - -lss_calcflicker \ - -lot_sensor_i2c \ - -lss_extend_stats \ - -lss_ir_auto \ - -lss_bnr \ - -lss_acs \ - -lss_drc \ - -lss_dehaze \ - -lss_ldci \ - -lss_crb \ - -lprotobuf-c \ - -lss_upvqe \ - -lss_dnvqe \ - -Wl,--as-needed \ - -lavdevice -lavformat -lavfilter -lavcodec -lswresample -lswscale -lavutil \ - -lpostproc -lx264 \ - -lpthread -lm -lstdc++ -ldl -lrt - -# 源文件列表 -SRCS := 264dec.cpp 264enc.cpp 265dec.cpp 265enc.cpp mjpegdec.cpp mjpegenc.cpp - -# 输出目录 -OUT_DIR := $(CURDIR)/out -TARGET_NAMES := $(SRCS:.cpp=) -TARGETS := $(addprefix $(OUT_DIR)/,$(TARGET_NAMES)) - -# 默认目标 -all: $(TARGETS) - -# 编译规则 -$(OUT_DIR)/%: %.cpp - @mkdir -p $(OUT_DIR) - $(CXX) -o $@ $< $(INCLUDES) $(LIB_PATHS) $(LDFLAGS) - @echo "✅ 编译完成: $@" - -# 清理目标 -clean: - rm -f $(TARGETS) - @echo "🧹 已清理生成文件" -~~~ - -~~~bash -make -~~~ - -![image-20251022155422517](./pic/image-20260429165747560.png) - -编译完成后out目录下生成可执行文件 - -![image-20260429165811417](./pic/image-20260429165811417.png) - -2.编译hisi案例: - -将hisi目录下的Makefile替换成以下的(注意路径替换) - -~~~bash -# 1. 根目录改为你的真实用户目录 -ROOT_DIR := /root - -# 2. 编译器改为 GCC(利用你配置好的 PATH 环境变量) -CXX := aarch64-openeuler-linux-gnu-g++ - -# 3. 头文件路径(指向 GCC 版本的 SDK) -INCLUDES := \ - -I${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/include \ - -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/include \ - -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common - -# 4. 库路径(指向 GCC 版本的库) -LIB_PATHS := \ - -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/hisi_sdk_lib \ - -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ - -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib \ - -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/svp_npu \ - -L${ROOT_DIR}/pegasus/vendor/opensource/x264/install/lib - -# 5. 链接选项(与海思 build_ffmpeg.sh 中 HISI_RUNTIME_LIBS_DEFAULT 对齐;须整块放在 --no-as-needed 内写入 DT_NEEDED) -LDFLAGS := \ - -Wl,-rpath,${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ - -Wl,--allow-shlib-undefined \ - -Wl,--no-as-needed \ - -lhisi_sdk_init \ - -lsecurec \ - -lot_base \ - -lot_osal \ - -lot_sys \ - -lot_chnl \ - -lot_rgn \ - -lot_gdc \ - -lot_vgs \ - -lot_dis \ - -lot_vpp \ - -lot_vi \ - -lot_isp \ - -lot_vpss \ - -lot_vo \ - -lot_vedu \ - -lot_rc \ - -lot_venc \ - -lot_h264e \ - -lot_h265e \ - -lot_jpege \ - -lot_jpegd \ - -lot_vfmw \ - -lot_vdec \ - -lot_irq \ - -lot_mpi_isp \ - -lss_ive \ - -lss_dpu_rect \ - -lss_dpu_match \ - -lss_mau \ - -lsvp_acl \ - -lot_aio \ - -lot_ai \ - -lot_ao \ - -lot_aenc \ - -lot_adec \ - -lot_acodec \ - -lot_pwm \ - -lot_piris \ - -lss_mpi \ - -lss_hdmi \ - -lss_isp \ - -lss_ae \ - -lss_awb \ - -lss_voice_engine \ - -lss_calcflicker \ - -lot_sensor_i2c \ - -lss_extend_stats \ - -lss_ir_auto \ - -lss_bnr \ - -lss_acs \ - -lss_drc \ - -lss_dehaze \ - -lss_ldci \ - -lss_crb \ - -lprotobuf-c \ - -lss_upvqe \ - -lss_dnvqe \ - -Wl,--as-needed \ - -lavdevice -lavformat -lavfilter -lavcodec -lswresample -lswscale -lavutil \ - -lpostproc -lx264 \ - -lpthread -lm -lstdc++ -ldl -lrt - -# 源文件列表 -SRCS := hisi_264vdec.cpp hisi_264venc.cpp hisi_265vdec.cpp hisi_265venc.cpp hisi_mjpegvdec.cpp hisi_mjpegvenc.cpp - -# 输出目录 -OUT_DIR := $(CURDIR)/out -TARGET_NAMES := $(SRCS:.cpp=) -TARGETS := $(addprefix $(OUT_DIR)/,$(TARGET_NAMES)) - -# 默认目标 -all: $(TARGETS) - -# 编译规则 -$(OUT_DIR)/%: %.cpp - @mkdir -p $(OUT_DIR) - $(CXX) -o $@ $< $(INCLUDES) $(LIB_PATHS) $(LDFLAGS) - @echo "✅ 编译完成: $@" - -# 清理目标 -clean: - rm -f $(TARGETS) - @echo "🧹 已清理生成文件" - -~~~ - -~~~bash -make -~~~ - -out目录下会生成可执行文件 - -![image-20260429165848869](./pic/image-20260429165848869.png) - -## 4、板端验证 - -### 步骤1:配置板端环境 - -* 1、确保开发板已经烧录目标系统(openEuler / 业务系统镜像等) -* 2、使用网线将开发板与你的电脑进行连接,确保二者处于同一局域网内 -* 3、配置开发板的IP地址,并确保开发板与电脑能够互相ping通 - -```sh -# 注意:这里的eth0的IP地址,请根据自己的网络IP网段进行合理配置 -ifconfig eth0 192.168.100.100 - -# 添加权限 -echo 0 9999999 > /proc/sys/net/ipv4/ping_group_range -``` - -![image-20251010094441549](pic/image-20251010094441549.png) - -### 步骤2:准备ffmpeg依赖文件 - -* 1、将第2章交叉编译生成的v4l2、x264、x265的install目录,下载并拷贝到NFS挂载目录 -* 2、将第三章交叉编译ffmpeg生成的install目录,下载并拷贝到NFS挂载目录 -* 3、将第三章步骤5,编译好后的sample目录,下载并拷贝到NFS挂载目录 -* 4、将libhisi_sdk_init.so下载并拷贝到ffmpeg_install/lib/目录下 -* 5、将mpp/out/lib下载并拷贝到NFS挂载目录 - -![image-20251022162128690](pic/image-20251022162128690.png) - -![image-20251022164347161](pic/image-20251022164347161.png) - -* 6、在开发板的命令行终端执行下面的命令,将电脑的nfs目录挂载到开发板的/mnt目录下(注意:这里请根据自己的IP地址及NFS配置进行合理的修改) - -```sh -mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt -``` - -![image-20251022162847658](pic/image-20251022162847658.png) - -* 因为我这里对每个库进行了打包,所以当我们把NFS挂载上后,需要对这些库进行解压才能正常使用 - -![image-20251022163123950](pic/image-20251022163123950.png) - -* 7、在开发板的命令行终端执行下面的命令,配置各个库的环境变量 - -```sh -export PATH=/root/zsks/ffmpeg_install/bin:$PATH -export LD_LIBRARY_PATH=/root/zsks/libv4l2_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/root/zsks/x264_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/root/zsks/x265_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/root/zsks/ffmpeg_install/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/root/zsks/lib/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH=/root/zsks/lib/lib:/root/zsks/lib/svp_npu/:$LD_LIBRARY_PATH - -export LD_LIBRARY_PATH=/usr/lib64:/usr/lib64/svp_npu:/root/ffmpeg/install/lib:$LD_LIBRARY_PATH -``` - -![image-20260429171601772](./pic/image-20260429171601772.png) - -### 步骤3:测试ffmpeg是否正常工作(有问题) - -* 在开发板的命令行,执行下面的命令,获取ffmpeg的版本号 - -```sh -cd /mnt/ffmpeg/ffmpeg_install/bin/ - -ffmpeg -version -``` - -![image-20260429174047698](./pic/image-20260429174047698.png) - - - -image-20251022170611820 - -### 步骤4:测试sample案例 - -* 注意:sample/hisi/目录下的是调用了海思硬件编解码模块,实现了硬件加速。sample/ffmpeg/目录下就是调用了ffmpeg的原始编解码接口。 -* 在开发板的命令行终端执行下面的命令,运行相关程序 - -```sh -cd /mnt/ffmpeg/sample/hisi - -chmod +x * - -# hisi编码 -./hisi_264venc /dev/video0 h264_ss928 640 480 30 - -cd /mnt/ffmpeg/sample/ffmpeg - -chmod +x * -# ffmpeg编码 -./264enc /dev/video0 640 480 30 -``` - -![image-20260429174602269](./pic/image-20260429174602269.png) - -![image-20251022175239062](pic/image-20251022175239062.png) - -![image-20251022175457018](pic/image-20251022175457018.png) - -* 在开发板的命令行分步执行下面的命令,测试解码案例 - -```sh -cd /mnt/ffmpeg/sample/hisi - -# hisi解码 -./hisi_264vdec h264_ss928_output.h264 output - -# ffmpeg解码 -./264dec libx264_output.h264 output -``` - -![image-20251022175651926](pic/image-20251022175651926.png) - -![image-20251022175749466](pic/image-20251022175749466.png) - -* 如果想在自己的代码中使用ffmpeg调用hisi的硬件编解码模块,可以使用avcodec_find_decoder_by_name接口来实现 - -```c -avcodec_find_decoder_by_name("h264ss928"); - -avcodec_find_decoder_by_name("h265_ss928"); - -avcodec_find_decoder_by_name("mjpeg_ss928"); - -avcodec_find_encoder_by_name("h264_ss928"); - -avcodec_find_encoder_by_name("h265_ss928"); - -avcodec_find_encoder_by_name("mjpeg_ss928"); -``` - -## 5、海思硬件编解码与ffmpeg原生编解码对比 - -* decoder - -| 数据/解码器 | h264 | h264_ss928 | hevc | h265_ss928 | mjpeg | mjpeg_ss928 | -| ------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | -| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | -| 总处理帧数 | 85 | 207 | 21 | 221 | 125 | 217 | -| 总解码时间(ms) | 4547.785 | 8592.903 | 4566.406 | 9147.614 | 3020.907 | 93398.829 | -| 总发送时间(ms) | | | 4566.203 | 8168.024(89.3%) | | 9007.92 | -| 总接收时间(ms) | | | 0.203 | 1004.696(10.7%) | | 335.712 | -| 平均解码时间(ms/帧) | 53.503 | 41.512 | 217.448 | 41.401 | 20.167 | 43.036 | -| 平均发送时间(ms/帧) | | | 217.438 | 36.959 | | | -| 平均接收时间(ms/帧) | | | 0.01 | 4.546 | | | -| 最短解码时间(ms) | 0.036 | 40.653 | 191.937 | 40.699 | 22.408 | 40.909 | -| 最长解码时间(ms) | 74.43 | 42.67 | 307.397 | 44.188 | 26.027 | 83.292 | -| 时间差值(ms) | 12.534 | | 115.46 | 3.489 | 3.599 | 42.383 | -| 解码帧率(FPS) | 18.69 | 24.09 | 4.6 | 24.15 | 41.38 | 23.24 | -| 每秒处理像素(MP/s) | | | 9.54 | 50.09 | 19.09 | 12.52 | - -* encoder - -| 数据/编码器 | libx264 | h264_ss928 | libx265 | h265_ss928 | mjpeg | mjpeg_ss928 | -| ----------------------------- | ------------------------ | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | -| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | -| 总处理帧数 | 85 | 208 | 21 | 222 | 114 | 218 | -| 总耗时(s) | 30.45 | 14.05 | 41.62 | 15.56 | 16.36 | 15.1 | -| 平均FPS | 11.19 | 14.8 | 0.5 | 14.27 | 6.97 | 14.44 | -| 平均格式转换时间(ms/帧) | 3 | 65.22 | 11.52 | 66.91 | 51.11 | 66.17 | -| 平均编码时间(ms/帧) | 342.35 | 2.25 | 1957.39 | 3.07 | 89.4 | 2.99 | -| 编码效率(编码时间/理论帧间隔) | 1027.05% | 6.74% | 5872.18% | 9.20% | 268.21% | 8.97% | -| 总编码时间(s) | 29.01 | 0.47 | 41.11 | 0.68 | 10.19 | 0.65 | -| 总转换时间(s) | 0.95 | 13.57 | 0.24 | 14.85 | 5.83 | 14.43 | -| 输出文件大小(MB) | 1.26 | | 0.32 | 13.28 | 17.44 | 11.86 | -| 压缩比 | 39.29:1 | | 192.04:1 | 49.60:1 | 19.39:1 | 54.52:1 | -| 平均码率(kbps) | 347.13 | | 65.39 | 7158.57 | 8941.11 | 6589.71 | -| 性能评级 | 极高压缩率,编码需要优化 | 编码优秀 | 压缩良好,编码不足 | 编码优秀 | 需优化 | 优秀 | +# FFmpeg移植 + +## 1、软硬件环境 + +* 开发板:海鸥派 +* 交叉编译工具链:openEuler aarch64 GCC(`aarch64-openeuler-linux-gnu-gcc`) + +* 编译链路径:`/root/openeuler_gcc_arm64le/bin` (根据实际修改) +* Python版本:Python-3.13.2 +* 移植的ffmpeg版本:FFmpeg-6.0 + +## 2、安装依赖 + +* 由于在编译ffmpeg的时候,需要依赖其他第三方软件,因此在编译ffmpeg之前,我们先把它依赖的第三方软件全部交叉编译出来。 + +### 步骤1:交叉编译v4l2 + +* 可以参考[v4l2的移植文档](../libv4l2/README.md)的前两章节,完成v4l2的移植工作。 + +### 步骤2:交叉编译x264 + +* 在服务器的命令行执行下面的命令,下载源码,配置编译链 + +```sh +cd /root/pegasus/vendor/opensource/ +git clone https://code.videolan.org/videolan/x264.git +cd x264 + + + wget -O config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' + wget -O config.sub 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' + +TOOLCHAIN_BIN="/root/openeuler_gcc_arm64le/bin" +CROSS_PREFIX="aarch64-openeuler-linux-gnu" +SYSROOT="$(${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --print-sysroot 2>/dev/null || true)" +SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" + +CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" \ +CXX="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++ --sysroot=${SYSROOT}" \ +CFLAGS="-march=armv8-a" \ +./configure \ + --host=aarch64-openeuler-linux-gnu \ + --prefix=$(pwd)/install \ + --enable-shared \ + --disable-cli + +make -j$(nproc) && make install +``` + +![image-20260429165209703](./pic/image-20260429165209703.png) + +* 编译成功后会在install目录下生成如下文件 + +![image-20260429165227713](./pic/image-20260429165227713.png) + +### 步骤3:交叉编译x265 + +* 在服务器的命令行执行下面的命令,下载源码 + +```sh +cd ../ +wget https://bitbucket.org/multicoreware/x265_git/downloads/x265_3.5.tar.gz + +#如果下载不成功尝试: +#打开浏览器访问:https://mirrors.tuna.tsinghua.edu.cn/debian/pool/main/x/x265/ +#找到文件 x265_3.5.orig.tar.gz +#下载到本地电脑。 + +tar xf x265_3.5.tar.gz +cd x265_3.5 +``` + +* 将下面内容添加到 build/aarch64-linux/crosscompile.cmake文件中 +* 注意:里面的库、头文件等的绝对路径请根据自己服务器的实际情况进行修改。 + +```sh +# crosscompile.cmake for x265 (openEuler GCC aarch64) +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +# ====== 你的工具链路径(按实际修改)====== +set(TOOLCHAIN_BIN "/root/openeuler_gcc_arm64le/bin") +set(CROSS_PREFIX "aarch64-openeuler-linux-gnu") + +# ====== 你的 sysroot(按实际修改)====== +set(CMAKE_SYSROOT "/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot") + +# compilers +set(CMAKE_C_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc") +set(CMAKE_CXX_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++") +set(CMAKE_ASM_COMPILER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc") + +# binutils +set(CMAKE_AR "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar") +set(CMAKE_RANLIB "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ranlib") +set(CMAKE_STRIP "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip") +set(CMAKE_NM "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-nm") +set(CMAKE_LINKER "${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ld") + +# ====== 关键:只在目标根路径里找库/头文件,避免混入宿主机 ====== +set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# ====== flags(保证 PIC + 明确 sysroot)====== +set(CMAKE_C_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC -march=armv8-a") +set(CMAKE_CXX_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC -march=armv8-a") +set(CMAKE_ASM_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT} -fPIC") + +set(CMAKE_EXE_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}") +set(CMAKE_SHARED_LINKER_FLAGS_INIT "--sysroot=${CMAKE_SYSROOT}") + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# (可选)如果你担心复用缓存导致误用宿主机编译器,可以打开这句强制: +# set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +``` + +![image-20260429165324954](./pic/image-20260429165324954.png) + + + +```sh +cd /root/pegasus/vendor/opensource/x265_3.5 + +mkdir build-aarch64 && cd build-aarch64 + +cmake ../source \ + -G "Unix Makefiles" \ + -DCMAKE_TOOLCHAIN_FILE=../build/aarch64-linux/crosscompile.cmake \ + -DCMAKE_INSTALL_PREFIX=/root/pegasus/vendor/opensource/x265_3.5/install \ + -DENABLE_SHARED=ON \ + -DENABLE_PIC=ON \ + -DENABLE_ASSEMBLY=OFF \ + -Wno-dev + +make -j"$(nproc)" && make install +``` + +![image-20260429165401463](./pic/image-20260429165401463.png) + +![image-20260429165426965](./pic/image-20260429165426965.png) + + + +* 编译完成后,会在install目录下生成如下文件 + +![image-20260429165455413](./pic/image-20260429165455413.png) + +## 3、交叉编译FFmpeg + +### 步骤1:下载源码 + +* 在服务器的命令行执行下面的命令,下载ffmpeg源码 + +```sh +cd ../ + +git clone -b release/6.0 https://gitee.com/zhongshankuangshi/ffmpeg.git + +cd ffmpeg +``` + +### 步骤2:环境变量配置 + +* 注意这里出现的决定路径的地址,请根据自己服务器的具体情况进行修改。 + +```sh +# 1. 设置工具链路径 +export TOOLCHAIN_BIN="/root/openeuler_gcc_arm64le/bin" +export CROSS_PREFIX="aarch64-openeuler-linux-gnu" +export SYSROOT="$(${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --print-sysroot 2>/dev/null || true)" +SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" + +export CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc" +export CXX="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++" +export AR="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar" +export LD="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ld" +export RANLIB="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ranlib" +export STRIP="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip" + +# 2. 设置依赖库路径 (请确保这些路径下的 lib 目录中存在 .so 或 .a 文件) +export X264_LIB="/root/pegasus/vendor/opensource/x264/install" +export X265_LIB="/root/pegasus/vendor/opensource/x265_3.5/install" +export V4L2_LIB="/root/pegasus/vendor/opensource/v4l-utils/install" + +# 3. 导出 PKG_CONFIG_PATH +export PKG_CONFIG_PATH="${X264_LIB}/lib/pkgconfig:${X265_LIB}/lib/pkgconfig:${V4L2_LIB}/lib/pkgconfig:$PKG_CONFIG_PATH" + +# 4. 导出 CFLAGS 和 LDFLAGS +export CFLAGS="-I${X264_LIB}/include -I${X265_LIB}/include -I${V4L2_LIB}/include --sysroot=${SYSROOT}" +export LDFLAGS="-L${X264_LIB}/lib -L${X265_LIB}/lib -L${V4L2_LIB}/lib --sysroot=${SYSROOT}" +``` + +### 步骤3:修改相关编译脚本 + +* 在pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common/Makefile的第4行,添加一个fPIC选项到CFLAGS,如下图所示: + +![image-20251022142837408](pic/image-20251022142837408.png) + +* 然后进入到pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common目录下,执行 make clean && make 命令,重新生成.o文件 +* 注意:请根据自己服务器的实际情况修改里面的绝对路径 + +```sh +cd /root/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common +make clean && make +``` + +![image-20260429165603344](./pic/image-20260429165603344.png) + +* 在ffmpeg目录下创建一个build_ffmpeg.sh脚本,把下面的内容复制进去 + +* 注意:请根据自己服务器的实际情况修改里面的绝对路径 + +![image-20251022150910879](pic/image-20251022150910879.png) + +```sh +#!/usr/bin/env bash +set -euo pipefail + +############################################# +# FFmpeg 交叉编译脚本(按 docs/gcc/ffmpeg/README.md 整理) +# - 生成 ./hisi_sdk_lib/libhisi_sdk_init.so +# - 配置并运行 FFmpeg ./configure +# +# 说明: +# - 你可以通过环境变量覆盖下面的路径(例如:X265_PATH=... ./build_ffmpeg.sh) +# - 本脚本会自动检测 pkg-config 是否能找到 x265;找不到则自动禁用 --enable-libx265 +############################################# + +msg() { printf '%s\n' "$*"; } +die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } + +VERBOSE="${VERBOSE:-0}" # 默认 0:减少输出;设为 1 显示详细信息 + +vmsg() { + [[ "${VERBOSE}" == "1" ]] && msg "$@" +} + +warn() { + # 统一 WARNING 输出,便于后续做收敛 + msg "WARNING: $*" +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || die "找不到命令:$1" +} + +pkg_has() { + local name="$1" + pkg-config --exists "$name" >/dev/null 2>&1 +} + +pkg_cflags() { + local name="$1" + pkg-config --cflags "$name" 2>/dev/null || true +} + +pkg_libs() { + local name="$1" + pkg-config --libs "$name" 2>/dev/null || true +} + +can_link_x265() { + # 返回 0 表示“真的能用 x265 编译+链接” + # 这比单纯 pkg-config --exists 更可信,能覆盖: + # - x265.pc 存在但路径错 + # - 只装了 pc 没装库/头文件 + # - pc 输出的 -L/-l 组合无法在交叉编译 sysroot 下链接 + # + # 注意:x265 本质是 C++ 实现(即便提供 C API 头文件), + # 仅用 $CC 链接经常会因为缺少 libstdc++ 等依赖而失败; + # 而 pkg-config 的 --libs 也不一定会把 -lstdc++ 带出来。 + # 所以这里用 $CXX 做最终链接,并补齐常见依赖。 + local tmpd + tmpd="$(mktemp -d)" + trap 'rm -rf "$tmpd"' RETURN + + local cflags libs + cflags="$(pkg_cflags x265)" + libs="$(pkg_libs x265)" + + if [[ -z "$cflags" || -z "$libs" ]]; then + return 1 + fi + + cat >"${tmpd}/conftest.cpp" <<'EOF' +#include +int main(void) { + x265_param p; + x265_param_default(&p); + return 0; +} +EOF + + # 注意:这里要用交叉编译器做真正的链接测试 + # 额外补齐常见的 C++ 运行库依赖(避免误判)。 + if ! "$CXX" --sysroot="${SYSROOT}" -o "${tmpd}/conftest" "${tmpd}/conftest.cpp" ${cflags} ${libs} -lstdc++ -lm -lpthread -ldl >/dev/null 2>&1; then + return 1 + fi + + return 0 +} + +add_pkg_dir_if_exists() { + local d="$1" + [[ -d "$d" ]] || return 0 + if [[ -z "${_PKG_DIRS:-}" ]]; then + _PKG_DIRS="$d" + else + _PKG_DIRS="${_PKG_DIRS}:$d" + fi +} + +setup_pkg_config_env() { + # 交叉编译时,尽量避免 pkg-config 混入宿主机默认路径。 + # + # 重要:PKG_CONFIG_SYSROOT_DIR 的行为是“把 .pc 里的前缀路径整体加上 sysroot”。 + # 如果你的三方库(x264/x265/v4l2)安装在 sysroot 外(例如 /root/pegasus/vendor/opensource/...), + # 那么启用 PKG_CONFIG_SYSROOT_DIR 会把路径变成: + # ${SYSROOT}/root/pegasus/vendor/opensource/... + # 从而导致找不到头文件/库,出现“pkg-config 能找到,但链接失败”的情况。 + # + # 因此这里做一个智能判定:只有当三方库前缀本身就在 SYSROOT 之下时,才启用 PKG_CONFIG_SYSROOT_DIR; + # 否则默认不设置(用户仍可通过环境变量强制设置)。 + + is_under_sysroot() { + local p="$1" + [[ -n "${SYSROOT:-}" ]] || return 1 + [[ "$p" == "${SYSROOT%/}/"* ]] + } + + local want_sysroot=0 + if [[ -n "${PKG_CONFIG_SYSROOT_DIR:-}" ]]; then + # 用户显式设置就尊重 + want_sysroot=1 + else + if is_under_sysroot "$X264_PATH" || is_under_sysroot "$X265_PATH" || is_under_sysroot "$V4L2_PATH"; then + want_sysroot=1 + fi + fi + + if [[ "$want_sysroot" == "1" ]]; then + export PKG_CONFIG_SYSROOT_DIR="${PKG_CONFIG_SYSROOT_DIR:-$SYSROOT}" + else + unset PKG_CONFIG_SYSROOT_DIR || true + fi + + _PKG_DIRS="" + + # 常见安装布局:lib/pkgconfig、lib64/pkgconfig、share/pkgconfig + add_pkg_dir_if_exists "${X264_PATH}/lib/pkgconfig" + add_pkg_dir_if_exists "${X264_PATH}/lib64/pkgconfig" + add_pkg_dir_if_exists "${X264_PATH}/share/pkgconfig" + + add_pkg_dir_if_exists "${X265_PATH}/lib/pkgconfig" + add_pkg_dir_if_exists "${X265_PATH}/lib64/pkgconfig" + add_pkg_dir_if_exists "${X265_PATH}/share/pkgconfig" + + add_pkg_dir_if_exists "${V4L2_PATH}/lib/pkgconfig" + add_pkg_dir_if_exists "${V4L2_PATH}/lib64/pkgconfig" + add_pkg_dir_if_exists "${V4L2_PATH}/share/pkgconfig" + + # 允许外部追加(但不要让它抢占我们的交叉编译路径) + if [[ -n "${PKG_CONFIG_PATH:-}" ]]; then + export PKG_CONFIG_PATH="${_PKG_DIRS}:${PKG_CONFIG_PATH}" + else + export PKG_CONFIG_PATH="${_PKG_DIRS}" + fi + + # 覆盖默认搜索目录,避免 /usr/lib/pkgconfig 等宿主路径影响检测 + export PKG_CONFIG_LIBDIR="${_PKG_DIRS}${PKG_CONFIG_LIBDIR:+:${PKG_CONFIG_LIBDIR}}" +} + +pc_file_hint() { + local prefix="$1" + local name="$2" + local cands=( + "${prefix}/lib/pkgconfig/${name}.pc" + "${prefix}/lib64/pkgconfig/${name}.pc" + "${prefix}/share/pkgconfig/${name}.pc" + ) + local c + for c in "${cands[@]}"; do + if [[ -f "$c" ]]; then + printf '%s' "$c" + return 0 + fi + done + # fallback:返回最常见的那个 + printf '%s' "${cands[0]}" + return 0 +} + +abspath() { + local p="$1" + if [[ "$p" == /* ]]; then + printf '%s' "$p" + else + printf '%s/%s' "$(pwd)" "$p" + fi +} + +# --- 1) 路径配置(可通过环境变量覆盖) --- +TOOLCHAIN_BIN="${TOOLCHAIN_BIN:-/root/openeuler_gcc_arm64le/bin}" +CROSS_PREFIX="${CROSS_PREFIX:-aarch64-openeuler-linux-gnu}" +SYSROOT="${SYSROOT:-$("${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc" --print-sysroot 2>/dev/null || true)}" +SYSROOT="${SYSROOT:-/root/openeuler_gcc_arm64le/aarch64-openeuler-linux-gnu/sysroot}" + +HISI_SDK_BASE="${HISI_SDK_BASE:-/root/pegasus/platform/ss928v100_gcc/smp/a55_linux}" +HISI_MPP_BASE="${HISI_MPP_BASE:-${HISI_SDK_BASE}/mpp}" +HISI_COMMON_DIR="${HISI_COMMON_DIR:-${HISI_SDK_BASE}/mpp/sample/common}" + +X264_PATH="${X264_PATH:-/root/pegasus/vendor/opensource/x264/install}" +X265_PATH="${X265_PATH:-/root/pegasus/vendor/opensource/x265_3.5/install}" +V4L2_PATH="${V4L2_PATH:-/root/pegasus/vendor/opensource/v4l-utils/install}" + +FF_PREFIX="${FF_PREFIX:-$(abspath ./install)}" +SDK_LIB_DIR="${SDK_LIB_DIR:-$(abspath ./hisi_sdk_lib)}" + +# --- 2) 工具链变量 --- +export CC="${CC:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc}" +export CXX="${CXX:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-g++}" +export AR="${AR:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-ar}" +export STRIP="${STRIP:-${TOOLCHAIN_BIN}/${CROSS_PREFIX}-strip}" + +require_cmd "$CC" +require_cmd "$CXX" +require_cmd "$AR" +require_cmd "$STRIP" +require_cmd pkg-config + +mkdir -p "$SDK_LIB_DIR" + +# --- 3) 构建 Hisi SDK 辅助库 --- +LINK_LIBS="-lss_mpi -lot_osal -lot_irq -lot_sys -lsecurec -lpthread -lm -lstdc++ -ldl -lrt" + +msg ">>> 正在构建 libhisi_sdk_init.so ..." +"$CC" -shared -fPIC --sysroot="${SYSROOT}" \ + -o "${SDK_LIB_DIR}/libhisi_sdk_init.so" \ + "${HISI_COMMON_DIR}/sdk_init.o" "${HISI_COMMON_DIR}/sdk_exit.o" \ + -L"${HISI_MPP_BASE}/out/lib" \ + ${LINK_LIBS} \ + -Wl,--allow-shlib-undefined + +msg "✓ libhisi_sdk_init.so 创建成功" + +# --- 4) pkg-config / include / lib 路径 --- +setup_pkg_config_env +EXTRA_CFLAGS="-fPIC -I${HISI_COMMON_DIR} -I${HISI_MPP_BASE}/include -I${HISI_SDK_BASE}/mpp/out/include --sysroot=${SYSROOT}" + +# 运行时依赖库白名单(参考 OpenHarmony/clang README 的 allowlist 思路) +# 背景: +# - 海思/MPP 的部分 .so 可能 DT_NEEDED 不完整,导致运行时出现: +# - /usr/lib64/libss_mpi.so: undefined symbol: voice_decode_frame +# - /usr/lib64/libot_sys.so: undefined symbol: cmpi_stop_modules +# - 解决思路:让最终 ffmpeg 可执行文件显式依赖一组“可能提供符号/初始化模块”的库, +# 并通过 --no-as-needed 强制写入 DT_NEEDED。 +# +# 可通过环境变量覆盖(建议按需裁剪,先全量保证能跑): +# HISI_RUNTIME_LIBS="-lot_sys -lot_osal -lss_mpi ..." +# +# 默认:尽量对齐 OpenHarmony 脚本 allowlist(偏全量,便于先跑通) +HISI_RUNTIME_LIBS_DEFAULT=( + -lsecurec + -lot_base + -lot_osal + -lot_sys + -lot_chnl + -lot_rgn + -lot_gdc + -lot_vgs + -lot_dis + -lot_vpp + -lot_vi + -lot_isp + -lot_vpss + -lot_vo + -lot_vedu + -lot_rc + -lot_venc + -lot_h264e + -lot_h265e + -lot_jpege + -lot_jpegd + -lot_vfmw + -lot_vdec + -lot_irq + -lot_mpi_isp + -lss_ive + -lss_dpu_rect + -lss_dpu_match + -lss_mau + -lsvp_acl + -lot_aio + -lot_ai + -lot_ao + -lot_aenc + -lot_adec + -lot_acodec + -lot_pwm + -lot_piris + -lss_mpi + -lss_hdmi + -lss_isp + -lss_ae + -lss_awb + -lss_voice_engine + -lss_calcflicker + -lot_sensor_i2c + -lss_extend_stats + -lss_ir_auto + -lss_bnr + -lss_acs + -lss_drc + -lss_dehaze + -lss_ldci + -lss_crb + -lprotobuf-c + -lss_upvqe + -lss_dnvqe +) + +# 关键:libss_mpi.so 未在 DT_NEEDED 中声明 libss_voice_engine,但依赖 voice_decode_frame; +# 该符号由 libss_voice_engine.so 提供,必须进入最终 ffmpeg 的 NEEDED,否则板端 symbol lookup 失败。 +HISI_RUNTIME_LIBS_ESSENTIAL=( + -lss_voice_engine +) + +library_exists_in_dirs() { + # $1: libname without "lib" prefix, e.g. "ot_sys" for -lot_sys + local name="${1:-}" + shift || true + [[ -n "$name" ]] || return 1 + local d + for d in "$@"; do + [[ -d "$d" ]] || continue + if [[ -f "$d/lib${name}.so" || -f "$d/lib${name}.so.0" || -f "$d/lib${name}.a" ]]; then + return 0 + fi + # 兼容带版本号的 so + if compgen -G "$d/lib${name}.so.*" >/dev/null 2>&1; then + return 0 + fi + done + return 1 +} + +filter_existing_link_flags() { + # 输入:一组 "-lxxx" flags + # 输出:只保留在给定 lib dirs 中能找到的 flags + local -a in_flags=("$@") + local -a out_flags=() + local -a missing_flags=() + local f name + for f in "${in_flags[@]}"; do + if [[ "$f" =~ ^-l(.+)$ ]]; then + name="${BASH_REMATCH[1]}" + if library_exists_in_dirs "$name" "${HISI_LIB_DIRS[@]}"; then + out_flags+=("$f") + else + missing_flags+=("$f") + fi + else + out_flags+=("$f") + fi + done + + if (( ${#missing_flags[@]} > 0 )); then + if [[ "${VERBOSE}" == "1" ]]; then + local mf + for mf in "${missing_flags[@]}"; do + warn "跳过不存在的库依赖:${mf}(在 ${HISI_LIB_DIRS[*]} 未找到对应的 lib*.so/.a)" + done + else + warn "有 ${#missing_flags[@]} 个 allowlist 库在 out/lib 中不存在,已自动跳过(如需列表:VERBOSE=1)" + fi + fi + printf '%s ' "${out_flags[@]}" +} + +if [[ -n "${HISI_RUNTIME_LIBS:-}" ]]; then + # shellcheck disable=SC2206 + HISI_RUNTIME_LIBS_ARR=( ${HISI_RUNTIME_LIBS} ) +else + HISI_RUNTIME_LIBS_ARR=( "${HISI_RUNTIME_LIBS_DEFAULT[@]}" ) +fi + +# Hisilicon/MPP 库目录(用于过滤 allowlist,避免 configure 链接测试直接失败) +HISI_LIB_DIRS=( + "${HISI_MPP_BASE}/out/lib" + "${HISI_MPP_BASE}/out/lib/svp_npu" + "${SDK_LIB_DIR}" +) + +# 必需库优先加入再过滤;若 SDK 中缺失则立刻失败,避免静默跳过导致 DT_NEEDED 不完整 +for _ess in "${HISI_RUNTIME_LIBS_ESSENTIAL[@]}"; do + if [[ "$_ess" =~ ^-l(.+)$ ]]; then + _n="${BASH_REMATCH[1]}" + if ! library_exists_in_dirs "$_n" "${HISI_LIB_DIRS[@]}"; then + die "缺少必需运行库:lib${_n}.so(${_ess}),无法链接 voice_decode_frame 等符号。请检查 HISI_MPP_BASE=${HISI_MPP_BASE}" + fi + fi +done + +# rpath:优先使用安装目录相对路径,其次允许你覆盖为板端系统目录 +# 默认增加 svp_npu(OpenHarmony README 也会把它加入 LD_LIBRARY_PATH) +TARGET_RPATH_DIR="${TARGET_RPATH_DIR:-\$ORIGIN/../lib}" +TARGET_RPATH_NPU_DIR="${TARGET_RPATH_NPU_DIR:-\$ORIGIN/../lib/svp_npu}" +RPATH_FLAGS=( + "-Wl,-rpath,${TARGET_RPATH_DIR}" + "-Wl,-rpath,${TARGET_RPATH_NPU_DIR}" + "-Wl,--enable-new-dtags" +) + +# 合并 essential + 用户/默认列表后再过滤(essential 已校验存在) +HISI_RUNTIME_LIBS_MERGED=( "${HISI_RUNTIME_LIBS_ESSENTIAL[@]}" "${HISI_RUNTIME_LIBS_ARR[@]}" ) +HISI_RUNTIME_LIBS_FILTERED="$(filter_existing_link_flags "${HISI_RUNTIME_LIBS_MERGED[@]}")" + +if [[ -z "${HISI_RUNTIME_LIBS_FILTERED// /}" ]]; then + die "HISI_RUNTIME_LIBS_FILTERED 为空(运行库 allowlist 全部被跳过)。请检查 HISI_MPP_BASE/out/lib 是否齐全。" +fi + +EXTRA_LDFLAGS="-fPIC -L${SDK_LIB_DIR} -L${HISI_MPP_BASE}/out/lib -lhisi_sdk_init \ + -L${HISI_MPP_BASE}/out/lib/svp_npu \ + -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed \ + ${RPATH_FLAGS[*]} \ + ${LINK_LIBS}" + +# --- 5) 自动处理 x265 not found using pkg-config --- +ENABLE_X265=1 +if ! pkg_has x265; then + ENABLE_X265=0 + msg "========================================" + msg "WARNING: pkg-config 找不到 x265,将自动禁用 --enable-libx265" + msg "- 期望的 .pc 路径:$(pc_file_hint "${X265_PATH}" x265)" + msg "- 当前 PKG_CONFIG_PATH:${PKG_CONFIG_PATH:-}" + msg "- 当前 PKG_CONFIG_LIBDIR:${PKG_CONFIG_LIBDIR:-}" + msg "- 当前 PKG_CONFIG_SYSROOT_DIR:${PKG_CONFIG_SYSROOT_DIR:-}" + msg "- 调试命令:pkg-config --print-errors --cflags --libs x265" + msg "如果你确认 x265 已安装,请检查 X265_PATH 是否指向正确 install 目录。" + msg "========================================" +else + # pkg-config 能找到不代表能链接,额外做一次真实的编译/链接探测 + if ! can_link_x265; then + ENABLE_X265=0 + msg "========================================" + msg "WARNING: pkg-config 能找到 x265,但交叉编译器无法用其输出完成链接,将自动禁用 --enable-libx265" + msg "- x265.pc:$(pc_file_hint "${X265_PATH}" x265)" + msg "- pkg-config --cflags x265:$(pkg_cflags x265)" + msg "- pkg-config --libs x265:$(pkg_libs x265)" + msg "- 建议你在服务器手动跑:" + msg " pkg-config --print-errors --cflags --libs x265" + msg " 并确认对应的 lib 目录下确实有 libx265.so / libx265.a" + msg "========================================" + fi +fi + +# x264 / v4l2 也做一下快速提示(缺了通常也会 configure 失败) +if ! pkg_has x264; then + msg "WARNING: pkg-config 找不到 x264(后续可能 configure 失败)。期望:$(pc_file_hint "${X264_PATH}" x264)" +fi +if ! pkg_has libv4l2; then + msg "WARNING: pkg-config 找不到 libv4l2(后续可能 configure 失败)。期望:$(pc_file_hint "${V4L2_PATH}" libv4l2)" +fi + +# --- 6) 准备 FFmpeg 编译参数 --- +CONFIGURE_ARGS=( + --prefix="${FF_PREFIX}" + --arch=aarch64 + --target-os=linux + --enable-cross-compile + --cc="${CC}" + --cxx="${CXX}" + --ar="${AR}" + --strip="${STRIP}" + --sysroot="${SYSROOT}" + --pkg-config="pkg-config" + --enable-gpl + --enable-libx264 + --enable-libv4l2 + --enable-encoder=h264_ss928,h265_ss928,mjpeg_ss928 + --enable-decoder=h264_ss928,h265_ss928,mjpeg_ss928 + --extra-cflags="${EXTRA_CFLAGS}" + --extra-ldflags="${EXTRA_LDFLAGS}" + --extra-ldexeflags="-Wl,--allow-shlib-undefined -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed ${RPATH_FLAGS[*]}" + --disable-static + --enable-shared +) + +if [[ "${ENABLE_X265}" == "1" ]]; then + CONFIGURE_ARGS+=( --enable-libx265 ) +fi + +msg "========================================" +msg "开始配置 FFmpeg..." +msg "========================================" + +print_config_log_tail() { + local log="ffbuild/config.log" + [[ -f "$log" ]] || return 0 + msg "" + msg "-------- ffbuild/config.log (last 120 lines) --------" + if command -v tail >/dev/null 2>&1; then + tail -n 120 "$log" 2>/dev/null || true + else + # fallback + sed -n '1h;1!H;${g;s/.*\\(\n.*\\)\\{120\\}/\\1/;p;}' "$log" 2>/dev/null || true + fi + msg "-----------------------------------------------------" +} + +print_compiler_test_errors() { + # 从 config.log 中尽量抽取“编译器自测失败”的真实报错行 + local log="ffbuild/config.log" + [[ -f "$log" ]] || return 0 + msg "" + msg "-------- compiler test related errors (grep) --------" + # 只抓高信号关键字,避免刷屏 + grep -nE "unable to create an executable file|C compiler test failed|collect2:|ld(\.bfd)?:|skipping incompatible|cannot find|crt1\.o|crti\.o|crtn\.o|libgcc|libc\.so" "$log" 2>/dev/null | tail -n 120 || true + msg "-----------------------------------------------------" +} + +run_configure() { + # 默认把 configure 输出收敛到日志文件,避免刷屏;失败时再摘出来 + local log="${CONFIGURE_LOG:-./ffbuild_configure.log}" + if [[ "${VERBOSE}" == "1" ]]; then + vmsg "configure 命令:./configure $*" + ./configure "$@" || return 1 + else + ./configure "$@" >"$log" 2>&1 || return 1 + fi + return 0 +} + +# 重要策略(已被你的日志验证): +# - 带一大串 HISI_RUNTIME_LIBS/--no-as-needed/rpath 的链接参数会让 configure 的“编译器自测”失败 +# - 但这些库又确实是板端运行时解 undefined symbol 必需的 +# 因此: +# 1) configure 阶段使用最小 ldflags 通过自测 +# 2) configure 成功后,再把 runtime libs / rpath 注入 ffbuild/config.mak(影响最终可执行文件链接) +CONFIGURE_ARGS_MIN=( + --prefix="${FF_PREFIX}" + --arch=aarch64 + --target-os=linux + --enable-cross-compile + --cc="${CC}" + --cxx="${CXX}" + --ar="${AR}" + --strip="${STRIP}" + --sysroot="${SYSROOT}" + --pkg-config="pkg-config" + --enable-gpl + --enable-libx264 + --enable-libv4l2 + --enable-encoder=h264_ss928,h265_ss928,mjpeg_ss928 + --enable-decoder=h264_ss928,h265_ss928,mjpeg_ss928 + --extra-cflags="${EXTRA_CFLAGS}" + # configure 阶段:只保留最基础的 ldflags(避免 allowlist/rpath 影响编译器自测) + --extra-ldflags="-fPIC -L${SDK_LIB_DIR} -L${HISI_MPP_BASE}/out/lib -L${HISI_MPP_BASE}/out/lib/svp_npu -lhisi_sdk_init ${LINK_LIBS}" + --extra-ldexeflags="-Wl,--allow-shlib-undefined" + --disable-static + --enable-shared +) +if [[ "${ENABLE_X265}" == "1" ]]; then + CONFIGURE_ARGS_MIN+=( --enable-libx265 ) +fi + +if ! run_configure "${CONFIGURE_ARGS_MIN[@]}"; then + msg "" + msg "❌ 配置失败。" + if [[ "${VERBOSE}" != "1" ]]; then + msg "提示:已将 configure 输出写入 ${CONFIGURE_LOG:-./ffbuild_configure.log}" + fi + msg "下面打印 config.log 末尾以便定位:" + print_config_log_tail + print_compiler_test_errors + + exit 1 +fi + +msg "" +msg "✅ 配置成功!将替换 ffbuild/config.mak 中的 LDEXEFLAGS(避免板端 undefined symbol)" + +patch_ffbuild_ldexeflags_line() { + # 旧实现使用文件末尾 LDEXEFLAGS+=,曾出现未参与最终链接的情况;改为直接改写唯一的 + # “LDEXEFLAGS= ...” 行,确保 ffmpeg/ffprobe 等可执行文件链接参数完整。 + local mk="ffbuild/config.mak" + [[ -f "$mk" ]] || die "找不到 ${mk}(configure 未成功生成)" + + # 删除旧版本脚本追加在文件末尾的注释 + LDEXEFLAGS+= 块(若存在) + if grep -q '^# HISI_RUNTIME_LIBS_INJECTED=1$' "$mk" 2>/dev/null; then + awk ' + /^# HISI_RUNTIME_LIBS_INJECTED=1$/ { skip = 1; next } + skip && /^LDEXEFLAGS\+=/ { skip = 0; next } + skip { next } + { print } + ' "$mk" >"${mk}.strip" && mv "${mk}.strip" "$mk" + fi + + local rf rf_make rpath_tail="" + for rf in "${RPATH_FLAGS[@]}"; do + rf_make="$(printf '%s' "$rf" | sed 's/\$/$$/g')" + rpath_tail+=" ${rf_make}" + done + + local new_line + new_line="LDEXEFLAGS= -Wl,--allow-shlib-undefined -Wl,--no-as-needed ${HISI_RUNTIME_LIBS_FILTERED} -Wl,--as-needed${rpath_tail}" + + local replaced=0 + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" == LDEXEFLAGS=* ]]; then + printf '%s\n' "$new_line" + replaced=1 + continue + fi + printf '%s\n' "$line" + done <"$mk" >"${mk}.new" + + if [[ "$replaced" != 1 ]]; then + rm -f "${mk}.new" + die "未在 ${mk} 中找到 LDEXEFLAGS= 行(可能 configure 输出格式变化),无法写入 Hisi 运行库链接参数" + fi + mv "${mk}.new" "$mk" + + msg "✓ 已替换 ${mk} 中的 LDEXEFLAGS(含 -lss_voice_engine 等,用于补齐 libss_mpi 未声明的 DT_NEEDED)" + vmsg ">>> 新 LDEXEFLAGS 预览(截断显示):${new_line:0:220}..." +} + +patch_ffbuild_ldexeflags_line + +msg "接下来请重新完整链接:make clean && make -j\$(nproc) && make install" +msg "(若仅增量 make,可能仍使用旧的 ffmpeg 链接结果;至少执行:rm -f ffmpeg_g fftools/ffmpeg_g && make -j\$(nproc))" +``` + +### 步骤4:编译ffmpeg + +* 在服务器的命令行,执行下面的命令,进行编译ffmpeg前的配置 + +```sh +chmod +x build_ffmpeg.sh + +./build_ffmpeg.sh +``` + +![image-20260429165631483](./pic/image-20260429165631483.png) + +* 在服务器的命令行,执行下面的命令,进行ffmpeg的编译 + +```sh +make -j$(nproc) && make install +``` + +![image-20260429165648074](./pic/image-20260429165648074.png) + +* 编译完成之后,会在install目录下生成下面的内容 +* 并且在ffmpeg目录下生成一个hisi_sdk_lib的文件夹,里面有一个libhisi_sdk_init.so库 + +![image-20260429165656879](./pic/image-20260429165656879.png) + +![image-20251022151540301](pic/image-20251022151540301.png) + +### 步骤5:编译sample + +* 在服务器的命令行,执行下面的命令,分别编译ffmpeg和hisi目录下的编解码案例 + +```sh +cd sample/ffmpeg +``` + +将Makefile替换成下面的(注意路径替换正确) + +~~~bash +# 1. 根目录改为你的真实用户目录 +ROOT_DIR := /root + +# 2. 编译器改为 GCC(利用你配置好的 PATH 环境变量) +CXX := aarch64-openeuler-linux-gnu-g++ + +# 3. 头文件路径(指向 GCC 版本的 SDK) +INCLUDES := \ + -I${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/include \ + -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/include \ + -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common + +# 4. 库路径(指向 GCC 版本的库) +LIB_PATHS := \ + -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/hisi_sdk_lib \ + -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ + -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib \ + -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/svp_npu \ + -L${ROOT_DIR}/pegasus/vendor/opensource/x264/install/lib + +# 5. 链接选项(与海思 build_ffmpeg.sh 中 HISI_RUNTIME_LIBS_DEFAULT 对齐;须整块放在 --no-as-needed 内写入 DT_NEEDED) +LDFLAGS := \ + -Wl,-rpath,${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ + -Wl,--allow-shlib-undefined \ + -Wl,--no-as-needed \ + -lhisi_sdk_init \ + -lsecurec \ + -lot_base \ + -lot_osal \ + -lot_sys \ + -lot_chnl \ + -lot_rgn \ + -lot_gdc \ + -lot_vgs \ + -lot_dis \ + -lot_vpp \ + -lot_vi \ + -lot_isp \ + -lot_vpss \ + -lot_vo \ + -lot_vedu \ + -lot_rc \ + -lot_venc \ + -lot_h264e \ + -lot_h265e \ + -lot_jpege \ + -lot_jpegd \ + -lot_vfmw \ + -lot_vdec \ + -lot_irq \ + -lot_mpi_isp \ + -lss_ive \ + -lss_dpu_rect \ + -lss_dpu_match \ + -lss_mau \ + -lsvp_acl \ + -lot_aio \ + -lot_ai \ + -lot_ao \ + -lot_aenc \ + -lot_adec \ + -lot_acodec \ + -lot_pwm \ + -lot_piris \ + -lss_mpi \ + -lss_hdmi \ + -lss_isp \ + -lss_ae \ + -lss_awb \ + -lss_voice_engine \ + -lss_calcflicker \ + -lot_sensor_i2c \ + -lss_extend_stats \ + -lss_ir_auto \ + -lss_bnr \ + -lss_acs \ + -lss_drc \ + -lss_dehaze \ + -lss_ldci \ + -lss_crb \ + -lprotobuf-c \ + -lss_upvqe \ + -lss_dnvqe \ + -Wl,--as-needed \ + -lavdevice -lavformat -lavfilter -lavcodec -lswresample -lswscale -lavutil \ + -lpostproc -lx264 \ + -lpthread -lm -lstdc++ -ldl -lrt + +# 源文件列表 +SRCS := 264dec.cpp 264enc.cpp 265dec.cpp 265enc.cpp mjpegdec.cpp mjpegenc.cpp + +# 输出目录 +OUT_DIR := $(CURDIR)/out +TARGET_NAMES := $(SRCS:.cpp=) +TARGETS := $(addprefix $(OUT_DIR)/,$(TARGET_NAMES)) + +# 默认目标 +all: $(TARGETS) + +# 编译规则 +$(OUT_DIR)/%: %.cpp + @mkdir -p $(OUT_DIR) + $(CXX) -o $@ $< $(INCLUDES) $(LIB_PATHS) $(LDFLAGS) + @echo "✅ 编译完成: $@" + +# 清理目标 +clean: + rm -f $(TARGETS) + @echo "🧹 已清理生成文件" +~~~ + +~~~bash +make +~~~ + +![image-20251022155422517](./pic/image-20260429165747560.png) + +编译完成后out目录下生成可执行文件 + +![image-20260429165811417](./pic/image-20260429165811417.png) + +2.编译hisi案例: + +将hisi目录下的Makefile替换成以下的(注意路径替换) + +~~~bash +# 1. 根目录改为你的真实用户目录 +ROOT_DIR := /root + +# 2. 编译器改为 GCC(利用你配置好的 PATH 环境变量) +CXX := aarch64-openeuler-linux-gnu-g++ + +# 3. 头文件路径(指向 GCC 版本的 SDK) +INCLUDES := \ + -I${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/include \ + -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/include \ + -I${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample/common + +# 4. 库路径(指向 GCC 版本的库) +LIB_PATHS := \ + -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/hisi_sdk_lib \ + -L${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ + -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib \ + -L${ROOT_DIR}/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/svp_npu \ + -L${ROOT_DIR}/pegasus/vendor/opensource/x264/install/lib + +# 5. 链接选项(与海思 build_ffmpeg.sh 中 HISI_RUNTIME_LIBS_DEFAULT 对齐;须整块放在 --no-as-needed 内写入 DT_NEEDED) +LDFLAGS := \ + -Wl,-rpath,${ROOT_DIR}/pegasus/vendor/opensource/ffmpeg/install/lib \ + -Wl,--allow-shlib-undefined \ + -Wl,--no-as-needed \ + -lhisi_sdk_init \ + -lsecurec \ + -lot_base \ + -lot_osal \ + -lot_sys \ + -lot_chnl \ + -lot_rgn \ + -lot_gdc \ + -lot_vgs \ + -lot_dis \ + -lot_vpp \ + -lot_vi \ + -lot_isp \ + -lot_vpss \ + -lot_vo \ + -lot_vedu \ + -lot_rc \ + -lot_venc \ + -lot_h264e \ + -lot_h265e \ + -lot_jpege \ + -lot_jpegd \ + -lot_vfmw \ + -lot_vdec \ + -lot_irq \ + -lot_mpi_isp \ + -lss_ive \ + -lss_dpu_rect \ + -lss_dpu_match \ + -lss_mau \ + -lsvp_acl \ + -lot_aio \ + -lot_ai \ + -lot_ao \ + -lot_aenc \ + -lot_adec \ + -lot_acodec \ + -lot_pwm \ + -lot_piris \ + -lss_mpi \ + -lss_hdmi \ + -lss_isp \ + -lss_ae \ + -lss_awb \ + -lss_voice_engine \ + -lss_calcflicker \ + -lot_sensor_i2c \ + -lss_extend_stats \ + -lss_ir_auto \ + -lss_bnr \ + -lss_acs \ + -lss_drc \ + -lss_dehaze \ + -lss_ldci \ + -lss_crb \ + -lprotobuf-c \ + -lss_upvqe \ + -lss_dnvqe \ + -Wl,--as-needed \ + -lavdevice -lavformat -lavfilter -lavcodec -lswresample -lswscale -lavutil \ + -lpostproc -lx264 \ + -lpthread -lm -lstdc++ -ldl -lrt + +# 源文件列表 +SRCS := hisi_264vdec.cpp hisi_264venc.cpp hisi_265vdec.cpp hisi_265venc.cpp hisi_mjpegvdec.cpp hisi_mjpegvenc.cpp + +# 输出目录 +OUT_DIR := $(CURDIR)/out +TARGET_NAMES := $(SRCS:.cpp=) +TARGETS := $(addprefix $(OUT_DIR)/,$(TARGET_NAMES)) + +# 默认目标 +all: $(TARGETS) + +# 编译规则 +$(OUT_DIR)/%: %.cpp + @mkdir -p $(OUT_DIR) + $(CXX) -o $@ $< $(INCLUDES) $(LIB_PATHS) $(LDFLAGS) + @echo "✅ 编译完成: $@" + +# 清理目标 +clean: + rm -f $(TARGETS) + @echo "🧹 已清理生成文件" + +~~~ + +~~~bash +make +~~~ + +out目录下会生成可执行文件 + +![image-20260429165848869](./pic/image-20260429165848869.png) + +## 4、板端验证 + +### 步骤1:配置板端环境 + +* 1、确保开发板已经烧录目标系统(openEuler / 业务系统镜像等) +* 2、使用网线将开发板与你的电脑进行连接,确保二者处于同一局域网内 +* 3、配置开发板的IP地址,并确保开发板与电脑能够互相ping通 + +```sh +# 注意:这里的eth0的IP地址,请根据自己的网络IP网段进行合理配置 +ifconfig eth0 192.168.100.100 + +# 添加权限 +echo 0 9999999 > /proc/sys/net/ipv4/ping_group_range +``` + +![image-20251010094441549](pic/image-20251010094441549.png) + +### 步骤2:准备ffmpeg依赖文件 + +* 1、将第2章交叉编译生成的v4l2、x264、x265的install目录,下载并拷贝到NFS挂载目录 +* 2、将第三章交叉编译ffmpeg生成的install目录,下载并拷贝到NFS挂载目录 +* 3、将第三章步骤5,编译好后的sample目录,下载并拷贝到NFS挂载目录 +* 4、将libhisi_sdk_init.so下载并拷贝到ffmpeg_install/lib/目录下 +* 5、将mpp/out/lib下载并拷贝到NFS挂载目录 + +![image-20251022162128690](pic/image-20251022162128690.png) + +![image-20251022164347161](pic/image-20251022164347161.png) + +* 6、在开发板的命令行终端执行下面的命令,将电脑的nfs目录挂载到开发板的/mnt目录下(注意:这里请根据自己的IP地址及NFS配置进行合理的修改) + +```sh +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20251022162847658](pic/image-20251022162847658.png) + +* 因为我这里对每个库进行了打包,所以当我们把NFS挂载上后,需要对这些库进行解压才能正常使用 + +![image-20251022163123950](pic/image-20251022163123950.png) + +* 7、在开发板的命令行终端执行下面的命令,配置各个库的环境变量 + +```sh +export PATH=/root/zsks/ffmpeg_install/bin:$PATH +export LD_LIBRARY_PATH=/root/zsks/libv4l2_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/root/zsks/x264_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/root/zsks/x265_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/root/zsks/ffmpeg_install/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/root/zsks/lib/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/root/zsks/lib/lib:/root/zsks/lib/svp_npu/:$LD_LIBRARY_PATH + +export LD_LIBRARY_PATH=/usr/lib64:/usr/lib64/svp_npu:/root/ffmpeg/install/lib:$LD_LIBRARY_PATH +``` + +![image-20260429171601772](./pic/image-20260429171601772.png) + +### 步骤3:测试ffmpeg是否正常工作(有问题) + +* 在开发板的命令行,执行下面的命令,获取ffmpeg的版本号 + +```sh +cd /mnt/ffmpeg/ffmpeg_install/bin/ + +ffmpeg -version +``` + +![image-20260429174047698](./pic/image-20260429174047698.png) + + + +image-20251022170611820 + +### 步骤4:测试sample案例 + +* 注意:sample/hisi/目录下的是调用了海思硬件编解码模块,实现了硬件加速。sample/ffmpeg/目录下就是调用了ffmpeg的原始编解码接口。 +* 在开发板的命令行终端执行下面的命令,运行相关程序 + +```sh +cd /mnt/ffmpeg/sample/hisi + +chmod +x * + +# hisi编码 +./hisi_264venc /dev/video0 h264_ss928 640 480 30 + +cd /mnt/ffmpeg/sample/ffmpeg + +chmod +x * +# ffmpeg编码 +./264enc /dev/video0 640 480 30 +``` + +![image-20260429174602269](./pic/image-20260429174602269.png) + +![image-20251022175239062](pic/image-20251022175239062.png) + +![image-20251022175457018](pic/image-20251022175457018.png) + +* 在开发板的命令行分步执行下面的命令,测试解码案例 + +```sh +cd /mnt/ffmpeg/sample/hisi + +# hisi解码 +./hisi_264vdec h264_ss928_output.h264 output + +# ffmpeg解码 +./264dec libx264_output.h264 output +``` + +![image-20251022175651926](pic/image-20251022175651926.png) + +![image-20251022175749466](pic/image-20251022175749466.png) + +* 如果想在自己的代码中使用ffmpeg调用hisi的硬件编解码模块,可以使用avcodec_find_decoder_by_name接口来实现 + +```c +avcodec_find_decoder_by_name("h264ss928"); + +avcodec_find_decoder_by_name("h265_ss928"); + +avcodec_find_decoder_by_name("mjpeg_ss928"); + +avcodec_find_encoder_by_name("h264_ss928"); + +avcodec_find_encoder_by_name("h265_ss928"); + +avcodec_find_encoder_by_name("mjpeg_ss928"); +``` + +## 5、海思硬件编解码与ffmpeg原生编解码对比 + +* decoder + +| 数据/解码器 | h264 | h264_ss928 | hevc | h265_ss928 | mjpeg | mjpeg_ss928 | +| ------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | +| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | +| 总处理帧数 | 85 | 207 | 21 | 221 | 125 | 217 | +| 总解码时间(ms) | 4547.785 | 8592.903 | 4566.406 | 9147.614 | 3020.907 | 93398.829 | +| 总发送时间(ms) | | | 4566.203 | 8168.024(89.3%) | | 9007.92 | +| 总接收时间(ms) | | | 0.203 | 1004.696(10.7%) | | 335.712 | +| 平均解码时间(ms/帧) | 53.503 | 41.512 | 217.448 | 41.401 | 20.167 | 43.036 | +| 平均发送时间(ms/帧) | | | 217.438 | 36.959 | | | +| 平均接收时间(ms/帧) | | | 0.01 | 4.546 | | | +| 最短解码时间(ms) | 0.036 | 40.653 | 191.937 | 40.699 | 22.408 | 40.909 | +| 最长解码时间(ms) | 74.43 | 42.67 | 307.397 | 44.188 | 26.027 | 83.292 | +| 时间差值(ms) | 12.534 | | 115.46 | 3.489 | 3.599 | 42.383 | +| 解码帧率(FPS) | 18.69 | 24.09 | 4.6 | 24.15 | 41.38 | 23.24 | +| 每秒处理像素(MP/s) | | | 9.54 | 50.09 | 19.09 | 12.52 | + +* encoder + +| 数据/编码器 | libx264 | h264_ss928 | libx265 | h265_ss928 | mjpeg | mjpeg_ss928 | +| ----------------------------- | ------------------------ | --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | +| 视频参数 | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | 1920x1080
@30FPS | +| 总处理帧数 | 85 | 208 | 21 | 222 | 114 | 218 | +| 总耗时(s) | 30.45 | 14.05 | 41.62 | 15.56 | 16.36 | 15.1 | +| 平均FPS | 11.19 | 14.8 | 0.5 | 14.27 | 6.97 | 14.44 | +| 平均格式转换时间(ms/帧) | 3 | 65.22 | 11.52 | 66.91 | 51.11 | 66.17 | +| 平均编码时间(ms/帧) | 342.35 | 2.25 | 1957.39 | 3.07 | 89.4 | 2.99 | +| 编码效率(编码时间/理论帧间隔) | 1027.05% | 6.74% | 5872.18% | 9.20% | 268.21% | 8.97% | +| 总编码时间(s) | 29.01 | 0.47 | 41.11 | 0.68 | 10.19 | 0.65 | +| 总转换时间(s) | 0.95 | 13.57 | 0.24 | 14.85 | 5.83 | 14.43 | +| 输出文件大小(MB) | 1.26 | | 0.32 | 13.28 | 17.44 | 11.86 | +| 压缩比 | 39.29:1 | | 192.04:1 | 49.60:1 | 19.39:1 | 54.52:1 | +| 平均码率(kbps) | 347.13 | | 65.39 | 7158.57 | 8941.11 | 6589.71 | +| 性能评级 | 极高压缩率,编码需要优化 | 编码优秀 | 压缩良好,编码不足 | 编码优秀 | 需优化 | 优秀 | diff --git a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251010094441549.png b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251010094441549.png index e981001ec636db595d2766310bf95a49e58f3914..63e1eaef2664fcd548632148c151d55fb61a91f5 100755 Binary files a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251010094441549.png and b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251010094441549.png differ diff --git a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251021205900311.png b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251021205900311.png index 995d820967e8a942a065956d51b38d48757d76a3..40aec69e251526ffd4d182524620bdebfa4a6dc8 100755 Binary files a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251021205900311.png and b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20251021205900311.png differ diff --git a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165441006.png b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165441006.png index a164f0eeffc813ea6ef6f49a0bd4ac2427e589b5..71065fa93bd08541a99d6e4d143fff47c0b423de 100755 Binary files a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165441006.png and b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165441006.png differ diff --git a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165455413.png b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165455413.png index a164f0eeffc813ea6ef6f49a0bd4ac2427e589b5..71065fa93bd08541a99d6e4d143fff47c0b423de 100755 Binary files a/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165455413.png and b/vendor/zsks/docs/gcc/ffmpeg/pic/image-20260429165455413.png differ diff --git a/vendor/zsks/docs/gcc/libcamera/README.md b/vendor/zsks/docs/gcc/libcamera/README.md index 58bcb40f401649a50ddd7f705a4c961139454762..bb3740b0151bfead2cb72b08b5f7eed282ba716b 100755 --- a/vendor/zsks/docs/gcc/libcamera/README.md +++ b/vendor/zsks/docs/gcc/libcamera/README.md @@ -20,8 +20,6 @@ cd pegasus/vendor/opensource/Python-3.13.2 . crossenv_aarch64/bin/activate ``` -![image-20251020160523558](pic/image-20251020160523558.png) - ## 3.安装依赖 * 由于在编译libacamera的时候,需要依赖其他第三方软件,因此在编译libacamera之前,我们先把它依赖的第三方软件全部交叉编译出来。 @@ -71,7 +69,7 @@ export SYSROOT="$(${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --print-sysroot 2>/dev/nu export CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" ``` -![image-20251020162138430](pic/image-20251020162138430.png) + ![image-20251020162307165](pic/image-20251020162307165.png) @@ -92,10 +90,6 @@ sed -i 's/arc4random_buf/libevent_arc4random_buf/g' evutil_rand.c make && make install ``` -![image-20251020162558010](pic/image-20251020162558010.png) - -![image-20251020162712286](pic/image-20251020162712286.png) - * 编译成功后,会在install目录下生成以下文件 ![image-20251020163215884](pic/image-20251020163215884.png) @@ -115,8 +109,6 @@ rm tiff-4.5.1.tar.gz cd tiff-4.5.1 ``` -![image-20251020163840912](pic/image-20251020163840912.png) - * 在服务器的命令行执行下面的命令,编译ttif ```sh @@ -128,10 +120,6 @@ cd tiff-4.5.1 make && make install ``` -![image-20251020164718454](pic/image-20251020164718454.png) - -![image-20251020164811557](pic/image-20251020164811557.png) - * 编译完成后,会在install目录下生成如下的文件 ![image-20251020165144726](pic/image-20251020165144726.png) @@ -151,8 +139,6 @@ rm jpegsrc.v9d.tar.gz cd jpegsrc.v9d ``` -![image-20251020165513929](pic/image-20251020165513929.png) - * 执行下面的命令,交叉编译jpeg-9d @@ -168,9 +154,7 @@ export CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" make && make install ``` -![image-20251020165719960](pic/image-20251020165719960.png) -![image-20251020165802562](pic/image-20251020165802562.png) * 编译完成后,会在install目录下生成如下的文件 @@ -198,11 +182,7 @@ make CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" \ make install ``` -![image-20251009173438071](pic/image-20251009173438071.png) - -![image-20251009173659012](pic/image-20251009173659012.png) -![image-20251009174036856](pic/image-20251009174036856.png) ![image-20251009174105488](pic/image-20251009174105488.png) @@ -217,8 +197,6 @@ apt-get install ninja-build libevent-dev libjpeg-dev pip3 install meson==1.6 jinja2 pyyaml ply pybind11 -i https://pypi.tuna.tsinghua.edu.cn/simple ``` -![image-20251020170606044](pic/image-20251020170606044.png) - ## 4、交叉编译libcamera ### 步骤1:下载源码 @@ -233,8 +211,6 @@ git clone https://git.libcamera.org/libcamera/libcamera.git cd libcamera ``` -![image-20251020172340245](pic/image-20251020172340245.png) - ### 步骤2:配置编译环境 * 在libcamera目录下创建一个cross_file.txt文件,然后把下面的内容复制进去。 diff --git a/vendor/zsks/docs/gcc/libcamera/pic/image-20251021105919871.png b/vendor/zsks/docs/gcc/libcamera/pic/image-20251021105919871.png index 6048787f578fa0534a0c728261b06812c4bdb0de..ea0477762d3a73ff2f105cca1520f49a2fe31009 100755 Binary files a/vendor/zsks/docs/gcc/libcamera/pic/image-20251021105919871.png and b/vendor/zsks/docs/gcc/libcamera/pic/image-20251021105919871.png differ diff --git a/vendor/zsks/docs/gcc/numpy/README.md b/vendor/zsks/docs/gcc/numpy/README.md index f1deabbfa06c219070d3fe2f5ea715de054ed69b..e011ad01375216a73d84e68928f0fa8dcb08c915 100755 --- a/vendor/zsks/docs/gcc/numpy/README.md +++ b/vendor/zsks/docs/gcc/numpy/README.md @@ -1,160 +1,154 @@ -# numpy移植 - -## 1、软硬件环境 - -开发板: -交叉编译工具链:openEuler aarch64 GCC(`aarch64-openeuler-linux-gnu-gcc`) - -编译链路径:`/home/gmy/openeuler/openeuler_gcc_arm64le/bin`(根据实际修改) - -移植的Python版本:Python-3.13.2 - -工作目录:`/home/gmy/pegasus/vendor/opensource` - -注:此移植在python3移植后进行,详情参考python3移植 - -提前设置环境: - -```bash -#配置网络 -ifconfig eth0 192.168.137.0 netmask 255.255.255.0 -route add default gw 192.168.137.1 -#设置python环境 -export PATH=/root/zsks/python3.13_install/bin:$PATH -export PYTHONPATH=/root/zsks/python3.13_install/lib/python3.13:$PYTHONPATH -export LD_LIBRARY_PATH=/root/zsks/python3.13_install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH -``` - -## 2、在设备端为python3安装pip - -```mk1.sh -python3 -m ensurepip --default-pip -``` - -![image-20260429192303917](./pic/image-20260429192303917.png) - -![image-20260429192356834](./pic/image-20260429192356834.png) - -## 3、更新pip - -3.1首先在python3 lib-dynload中放入交叉编译openssl生成的 libssl.so.1.1 和 libcrypto.so.1.1 文件 - -![image-20260429192441720](./pic/image-20260429192441720.png) - -3.2让板端联网,在网络共享页面先把√都取消,然后选择与当前连接的网线网络(如以太网)共享WiFi,确认后再重新√上,再次确认,即可上网 - -![image-20260429192617211](./pic/image-20260429192617211.png) - -![image-20260429192623348](./pic/image-20260429192623348.png) - -![image-20260429192628880](./pic/image-20260429192628880.png) - -3.3ping百度网站,看是否连上网络 - -```mk1.sh -ping www.baidu.com -``` - -![image-20260429192651197](./pic/image-20260429192651197.png) - -```mk1.sh -python3 -m pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ -``` - -![image-20260429192835585](./pic/image-20260429192835585.png) - -## 4、使用pip下载numpy - -```mk1.sh -pip install numpy==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ -``` - -![image-20260429192942291](./pic/image-20260429192942291.png) - -简单测试: - -~~~bash -python3 -import numpy -~~~ - -![image-20260429193016042](./pic/image-20260429193016042.png) - -## 5、板端测试 - -- 将下面的内容复制到numpy_test.py中 - -```python -import numpy as np -import time - -def test_numpy_functionality(): - """测试 NumPy 的基本功能""" - print("=" * 50) - print("NumPy 功能测试") - print("=" * 50) - - # 1. 创建数组 - arr1 = np.array([1, 2, 3, 4, 5]) - arr2 = np.arange(0, 10, 2) # 类似 range,但生成数组 - arr3 = np.zeros((3, 3)) # 3x3 零矩阵 - arr4 = np.random.rand(2, 2) # 2x2 随机矩阵 - - print("\n1. 数组创建:") - print(f"arr1: {arr1}") - print(f"arr2 (0到10步长2): {arr2}") - print(f"arr3 (3x3零矩阵):\n{arr3}") - print(f"arr4 (2x2随机矩阵):\n{arr4}") - - # 2. 数学运算 - print("\n2. 数学运算:") - print(f"arr1 + 10: {arr1 + 10}") # 广播机制 - print(f"arr1 * arr2 (前5项): {arr1 * arr2[:5]}") - print(f"sin(arr2): {np.sin(arr2)}") # 三角函数 - - # 3. 矩阵乘法 - matrix_a = np.array([[1, 2], [3, 4]]) - matrix_b = np.array([[5, 6], [7, 8]]) - dot_product = np.dot(matrix_a, matrix_b) # 矩阵乘法 - print("\n3. 矩阵乘法 (np.dot):") - print(f"matrix_a:\n{matrix_a}") - print(f"matrix_b:\n{matrix_b}") - print(f"结果:\n{dot_product}") - - # 4. 性能对比:NumPy vs 纯Python - print("\n4. 性能对比 (计算1百万个数的平方):") - size = 1_000_000 - - # 纯Python - py_list = list(range(size)) - start = time.time() - py_result = [x ** 2 for x in py_list] - py_time = time.time() - start - - # NumPy - np_arr = np.arange(size) - start = time.time() - np_result = np_arr ** 2 - np_time = time.time() - start - - print(f"纯Python耗时: {py_time:.5f} 秒") - print(f"NumPy耗时: {np_time:.5f} 秒") - print(f"NumPy比Python快 {py_time / np_time:.1f} 倍!") - - # 5. 高级功能:条件筛选 - print("\n5. 条件筛选 (找出arr2中大于5的数):") - filtered = arr2[arr2 > 5] - print(f"原始数组: {arr2}") - print(f"筛选结果: {filtered}") - -if __name__ == "__main__": - test_numpy_functionality() -``` - -- 然后执行下面的命令,运行numpy测试代码 - -```sh -python3 numpy_test.py -``` - -‍![image-20260429193204312](./pic/image-20260429193204312.png) +# numpy移植 + +## 1、软硬件环境 + +开发板: +交叉编译工具链:openEuler aarch64 GCC(`aarch64-openeuler-linux-gnu-gcc`) + +编译链路径:`/home/gmy/openeuler/openeuler_gcc_arm64le/bin`(根据实际修改) + +移植的Python版本:Python-3.13.2 + +工作目录:`/home/gmy/pegasus/vendor/opensource` + +注:此移植在python3移植后进行,详情参考python3移植 + +提前设置环境: + +```bash +#配置网络 +ifconfig eth0 192.168.137.0 netmask 255.255.255.0 +route add default gw 192.168.137.1 +#设置python环境 +export PATH=/root/zsks/python3.13_install/bin:$PATH +export PYTHONPATH=/root/zsks/python3.13_install/lib/python3.13:$PYTHONPATH +export LD_LIBRARY_PATH=/root/zsks/python3.13_install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH +``` + +## 2、在设备端为python3安装pip + +```mk1.sh +python3 -m ensurepip --default-pip +``` + +## 3、更新pip + +3.1首先在python3 lib-dynload中放入交叉编译openssl生成的 libssl.so.1.1 和 libcrypto.so.1.1 文件 + +![image-20260429192441720](./pic/image-20260429192441720.png) + +3.2让板端联网,在网络共享页面先把√都取消,然后选择与当前连接的网线网络(如以太网)共享WiFi,确认后再重新√上,再次确认,即可上网 + +![image-20260429192617211](./pic/image-20260429192617211.png) + +![image-20260429192623348](./pic/image-20260429192623348.png) + +![image-20260429192628880](./pic/image-20260429192628880.png) + +3.3ping百度网站,看是否连上网络 + +```mk1.sh +ping www.baidu.com +``` + +![image-20260429192651197](./pic/image-20260429192651197.png) + +```mk1.sh +python3 -m pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ +``` + +## 4、使用pip下载numpy + +```mk1.sh +pip install numpy==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ +``` + + + +简单测试: + +~~~bash +python3 +import numpy +~~~ + +![image-20260429193016042](./pic/image-20260429193016042.png) + +## 5、板端测试 + +- 将下面的内容复制到numpy_test.py中 + +```python +import numpy as np +import time + +def test_numpy_functionality(): + """测试 NumPy 的基本功能""" + print("=" * 50) + print("NumPy 功能测试") + print("=" * 50) + + # 1. 创建数组 + arr1 = np.array([1, 2, 3, 4, 5]) + arr2 = np.arange(0, 10, 2) # 类似 range,但生成数组 + arr3 = np.zeros((3, 3)) # 3x3 零矩阵 + arr4 = np.random.rand(2, 2) # 2x2 随机矩阵 + + print("\n1. 数组创建:") + print(f"arr1: {arr1}") + print(f"arr2 (0到10步长2): {arr2}") + print(f"arr3 (3x3零矩阵):\n{arr3}") + print(f"arr4 (2x2随机矩阵):\n{arr4}") + + # 2. 数学运算 + print("\n2. 数学运算:") + print(f"arr1 + 10: {arr1 + 10}") # 广播机制 + print(f"arr1 * arr2 (前5项): {arr1 * arr2[:5]}") + print(f"sin(arr2): {np.sin(arr2)}") # 三角函数 + + # 3. 矩阵乘法 + matrix_a = np.array([[1, 2], [3, 4]]) + matrix_b = np.array([[5, 6], [7, 8]]) + dot_product = np.dot(matrix_a, matrix_b) # 矩阵乘法 + print("\n3. 矩阵乘法 (np.dot):") + print(f"matrix_a:\n{matrix_a}") + print(f"matrix_b:\n{matrix_b}") + print(f"结果:\n{dot_product}") + + # 4. 性能对比:NumPy vs 纯Python + print("\n4. 性能对比 (计算1百万个数的平方):") + size = 1_000_000 + + # 纯Python + py_list = list(range(size)) + start = time.time() + py_result = [x ** 2 for x in py_list] + py_time = time.time() - start + + # NumPy + np_arr = np.arange(size) + start = time.time() + np_result = np_arr ** 2 + np_time = time.time() - start + + print(f"纯Python耗时: {py_time:.5f} 秒") + print(f"NumPy耗时: {np_time:.5f} 秒") + print(f"NumPy比Python快 {py_time / np_time:.1f} 倍!") + + # 5. 高级功能:条件筛选 + print("\n5. 条件筛选 (找出arr2中大于5的数):") + filtered = arr2[arr2 > 5] + print(f"原始数组: {arr2}") + print(f"筛选结果: {filtered}") + +if __name__ == "__main__": + test_numpy_functionality() +``` + +- 然后执行下面的命令,运行numpy测试代码 + +```sh +python3 numpy_test.py +``` + +‍![image-20260429193204312](./pic/image-20260429193204312.png) diff --git a/vendor/zsks/docs/gcc/opencv/README.md b/vendor/zsks/docs/gcc/opencv/README.md index f81b5b3964a7f49c1a85ef3c7ddc0dbc1f86fcf4..5d54fe36f74fbb0e32256042c09eb714464739d3 100755 --- a/vendor/zsks/docs/gcc/opencv/README.md +++ b/vendor/zsks/docs/gcc/opencv/README.md @@ -117,10 +117,6 @@ cd build make install ``` -![image-20251013150714220](pic/image-20251013150714220.png) - -![image-20260429164101725](./pic/image-20260429164101725.png) - * 安装成功后,会在install目录下生成以下文件。![image-20260429164111444](./pic/image-20260429164111444.png) ## 3、使用python调用OpenCV接口 diff --git "a/vendor/zsks/docs/gcc/opencv/opencv-python\347\247\273\346\244\215.md" "b/vendor/zsks/docs/gcc/opencv/opencv-python\347\247\273\346\244\215.md" index 8824dccb91a3861dbf2227d945806886d48f2527..2144fbfaec32c54f90329a822fdf50929b7cc19a 100755 --- "a/vendor/zsks/docs/gcc/opencv/opencv-python\347\247\273\346\244\215.md" +++ "b/vendor/zsks/docs/gcc/opencv/opencv-python\347\247\273\346\244\215.md" @@ -1,250 +1,248 @@ -# opencv-python移植 - -## 1、软硬件环境 - -开发板: - -python版本:Python-3.13.2 - -移植的numpy版本:numpy-v2.2.5 - -opencv版本:opencv-v4.12.0.88 - -注:此移植在python3移植和numpy移植后进行,详情参考python3移植和numpy移植 - -提前设置环境: - -```mk1.sh -#配置网络 -ifconfig eth0 hw ether 00:d1:f3:09:bd:0c -ifconfig eth0 192.168.137.0 netmask 255.255.255.0 -#设置python环境 -export PATH=/root/zsks/python3.13_install/bin:$PATH -export PYTHONPATH=/root/zsks/python3.13_install/lib/python3.13:$PYTHONPATH -export LD_LIBRARY_PATH=/root/zsks/python3.13_install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH -``` - -## 2、使用pip下载opencv-python-headless - -下载opencv-python无GUI版本 - -```mk1.sh -pip install opencv-python-headless -i https://pypi.tuna.tsinghua.edu.cn/simple/ -``` - -![image-20260429194217659](./pic/image-20260429194217659.png) - -## 3、板端测试 - -3.1测试opencv-python基本功能,将下面的内容复制到opencv_test.py中 - -```mk1.sh -import cv2 -import numpy as np -import os - -def test_opencv_without_ui(): - """无UI的OpenCV功能测试(通过文件保存和日志输出验证)""" - print("=" * 50) - print("OpenCV 无UI测试") - print("=" * 50) - - # 创建临时测试目录 - os.makedirs("opencv_test_output", exist_ok=True) - print("[日志] 创建输出目录: opencv_test_output") - - # 1. 生成测试图像 - test_image = np.zeros((200, 200, 3), dtype=np.uint8) - cv2.rectangle(test_image, (50, 50), (150, 150), (0, 255, 0), 2) - cv2.putText(test_image, "OpenCV Test", (30, 30), - cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) - cv2.imwrite("opencv_test_output/test_image.png", test_image) - print("[日志] 生成测试图像: test_image.png") - - # 2. 图像处理(灰度化+边缘检测) - gray_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2GRAY) - edges = cv2.Canny(gray_image, 100, 200) - cv2.imwrite("opencv_test_output/edges.png", edges) - print("[日志] 生成边缘检测结果: edges.png") - - # 3. 矩阵运算测试(修复:转换为float32) - mat_a = np.random.rand(3, 3).astype(np.float32) # 改为浮点矩阵 - mat_b = np.random.rand(3, 3).astype(np.float32) - mat_mult = cv2.gemm(mat_a, mat_b, 1, None, 0) - print("[矩阵运算] A * B = \n", mat_mult) - - # 4. 摄像头测试(无UI模式) - cap = cv2.VideoCapture(0) - if not cap.isOpened(): - print("[警告] 未检测到摄像头,跳过摄像头测试") - else: - ret, frame = cap.read() - if ret: - cv2.imwrite("opencv_test_output/camera_capture.png", frame) - print("[日志] 摄像头捕获成功: camera_capture.png") - cap.release() - - # 5. 特征检测(ORB) - orb = cv2.ORB_create() - kp = orb.detect(gray_image, None) - kp_image = cv2.drawKeypoints(gray_image, kp, None, color=(0, 255, 0)) - cv2.imwrite("opencv_test_output/keypoints.png", kp_image) - print("[日志] 生成特征点检测结果: keypoints.png") - print(f"[特征检测] 共检测到 {len(kp)} 个特征点") - - # 6. 性能测试 - start_time = cv2.getTickCount() - for _ in range(100): - _ = cv2.blur(test_image, (5, 5)) - end_time = cv2.getTickCount() - print(f"[性能] 100次模糊运算耗时: {(end_time - start_time)/cv2.getTickFrequency():.4f}秒") - - print("\n测试完成!结果已保存至 opencv_test_output 目录") - -if __name__ == "__main__": - test_opencv_without_ui() -``` - -然后执行下面的命令,运行opencv测试代码 - -```mk1.sh -python3 opencv_test.py -``` - -![image-20260429194406421](./pic/image-20260429194406421.png) - -![image-20260429194459690](./pic/image-20260429194459690.png) - -3.2测试opencv-python调用usb摄像头,将下面的内容复制到opencv_usb_test.py中 - -```mk1.sh -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import cv2 -import time - -def main(device_index=0, num_frames=100, backend=cv2.CAP_V4L2): - """ - 在无 UI 情况下从 USB 摄像头读取 num_frames 帧并打印每帧的尺寸。 - - :param device_index: 摄像头索引,0 表示第一个设备 - :param num_frames: 要读取的帧数 - :param backend: OpenCV 后端,可选 CAP_V4L2、CAP_ANY 等 - """ - # 打开摄像头 - cap = cv2.VideoCapture(device_index, backend) - if not cap.isOpened(): - print(f"无法打开摄像头 (index={device_index})") - return - - print("开始读取帧…按 Ctrl+C 可中断") - - try: - for i in range(num_frames): - ret, frame = cap.read() - if not ret: - print(f"第 {i} 帧读取失败,退出") - break - - # 示例处理:打印帧的分辨率 - h, w = frame.shape[:2] - print(f"帧 {i+1}/{num_frames} 大小:{w}x{h}") - - # 模拟处理时间 - time.sleep(0.01) - - except KeyboardInterrupt: - print("用户中断") - finally: - cap.release() - print("摄像头已释放,程序结束") - -if __name__ == "__main__": - # 可以通过修改以下参数来指定设备号或读取帧数 - main(device_index=0, num_frames=200) - -``` - -然后执行下面的命令,运行opencv usb测试代码 - -```mk1.sh -python3 opencv_usb_test.py -``` - -![image-20260429194609500](./pic/image-20260429194609500.png) - -3.3测试opencv-python中dnn模块 - -![image-20260429194639010](./pic/image-20260429194639010.png) - -测试代码:代码中FaceDetectorYN 依赖底层的dnn模块,封装后无需前处理,效果更好,dnn_test.py - -```mk1.sh -import cv2 - -# 1. 读取图片 -image_path = "image.jpg" # 替换为你的图片路径 -img = cv2.imread(image_path) -if img is None: - print("无法加载图片") - exit(1) -orig_h, orig_w = img.shape[:2] - -# 2. 初始化 FaceDetectorYN,使用原图大小并调松参数 -detector = cv2.FaceDetectorYN.create( - model="face_detection_yunet_2023mar.onnx", - config="", - input_size=(orig_w, orig_h), # 与原图一致 - score_threshold=0.4, # 提高置信度阈值到 0.4 - nms_threshold=0.5, # NMS 阈值 - top_k=200 # 保留最多 200 个候选 -) - -# 3. 检测人脸 -_, faces = detector.detect(img) - -# 4. 后处理:剔除过小的框 -min_size = 50 # 小于 50 像素的宽高都视为噪声 -filtered = [] -if faces is not None: - for face in faces: - x, y, w, h, score = face[:5].astype(int) - # 保留宽高都不小于阈值的框 - if w >= min_size and h >= min_size: - filtered.append((x, y, w, h, score)) - -# 5. 在图像上绘制过滤后的人脸框 -for x, y, w, h, score in filtered: - cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) - cv2.putText( - img, - f"{score/100:.2f}", - (x, y - 5), - cv2.FONT_HERSHEY_SIMPLEX, - 0.5, - (0, 255, 0), - 1 - ) - -# 6. 保存结果并输出检测到的人脸数量 -output_path = "output_image.jpg" -cv2.imwrite(output_path, img) -print(f"检测完成,检测到 {len(filtered)} 张人脸,结果已保存到 {output_path}") -``` - -运行以下命令进行测试: - -```mk1.sh -python3 dnn_test.py -``` - -![image-20260429194651455](./pic/image-20260429194651455.png) - -检测结果: - -![image-20260429194703200](./pic/image-20260429194703200.png) - - - -‍ +# opencv-python移植 + +## 1、软硬件环境 + +开发板: + +python版本:Python-3.13.2 + +移植的numpy版本:numpy-v2.2.5 + +opencv版本:opencv-v4.12.0.88 + +注:此移植在python3移植和numpy移植后进行,详情参考python3移植和numpy移植 + +提前设置环境: + +```mk1.sh +#配置网络 +ifconfig eth0 hw ether 00:d1:f3:09:bd:0c +ifconfig eth0 192.168.137.0 netmask 255.255.255.0 +#设置python环境 +export PATH=/root/zsks/python3.13_install/bin:$PATH +export PYTHONPATH=/root/zsks/python3.13_install/lib/python3.13:$PYTHONPATH +export LD_LIBRARY_PATH=/root/zsks/python3.13_install/lib/python3.13/lib-dynload:$LD_LIBRARY_PATH +``` + +## 2、使用pip下载opencv-python-headless + +下载opencv-python无GUI版本 + +```mk1.sh +pip install opencv-python-headless -i https://pypi.tuna.tsinghua.edu.cn/simple/ +``` + +## 3、板端测试 + +3.1测试opencv-python基本功能,将下面的内容复制到opencv_test.py中 + +```mk1.sh +import cv2 +import numpy as np +import os + +def test_opencv_without_ui(): + """无UI的OpenCV功能测试(通过文件保存和日志输出验证)""" + print("=" * 50) + print("OpenCV 无UI测试") + print("=" * 50) + + # 创建临时测试目录 + os.makedirs("opencv_test_output", exist_ok=True) + print("[日志] 创建输出目录: opencv_test_output") + + # 1. 生成测试图像 + test_image = np.zeros((200, 200, 3), dtype=np.uint8) + cv2.rectangle(test_image, (50, 50), (150, 150), (0, 255, 0), 2) + cv2.putText(test_image, "OpenCV Test", (30, 30), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) + cv2.imwrite("opencv_test_output/test_image.png", test_image) + print("[日志] 生成测试图像: test_image.png") + + # 2. 图像处理(灰度化+边缘检测) + gray_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2GRAY) + edges = cv2.Canny(gray_image, 100, 200) + cv2.imwrite("opencv_test_output/edges.png", edges) + print("[日志] 生成边缘检测结果: edges.png") + + # 3. 矩阵运算测试(修复:转换为float32) + mat_a = np.random.rand(3, 3).astype(np.float32) # 改为浮点矩阵 + mat_b = np.random.rand(3, 3).astype(np.float32) + mat_mult = cv2.gemm(mat_a, mat_b, 1, None, 0) + print("[矩阵运算] A * B = \n", mat_mult) + + # 4. 摄像头测试(无UI模式) + cap = cv2.VideoCapture(0) + if not cap.isOpened(): + print("[警告] 未检测到摄像头,跳过摄像头测试") + else: + ret, frame = cap.read() + if ret: + cv2.imwrite("opencv_test_output/camera_capture.png", frame) + print("[日志] 摄像头捕获成功: camera_capture.png") + cap.release() + + # 5. 特征检测(ORB) + orb = cv2.ORB_create() + kp = orb.detect(gray_image, None) + kp_image = cv2.drawKeypoints(gray_image, kp, None, color=(0, 255, 0)) + cv2.imwrite("opencv_test_output/keypoints.png", kp_image) + print("[日志] 生成特征点检测结果: keypoints.png") + print(f"[特征检测] 共检测到 {len(kp)} 个特征点") + + # 6. 性能测试 + start_time = cv2.getTickCount() + for _ in range(100): + _ = cv2.blur(test_image, (5, 5)) + end_time = cv2.getTickCount() + print(f"[性能] 100次模糊运算耗时: {(end_time - start_time)/cv2.getTickFrequency():.4f}秒") + + print("\n测试完成!结果已保存至 opencv_test_output 目录") + +if __name__ == "__main__": + test_opencv_without_ui() +``` + +然后执行下面的命令,运行opencv测试代码 + +```mk1.sh +python3 opencv_test.py +``` + +![image-20260429194406421](./pic/image-20260429194406421.png) + +![image-20260429194459690](./pic/image-20260429194459690.png) + +3.2测试opencv-python调用usb摄像头,将下面的内容复制到opencv_usb_test.py中 + +```mk1.sh +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import cv2 +import time + +def main(device_index=0, num_frames=100, backend=cv2.CAP_V4L2): + """ + 在无 UI 情况下从 USB 摄像头读取 num_frames 帧并打印每帧的尺寸。 + + :param device_index: 摄像头索引,0 表示第一个设备 + :param num_frames: 要读取的帧数 + :param backend: OpenCV 后端,可选 CAP_V4L2、CAP_ANY 等 + """ + # 打开摄像头 + cap = cv2.VideoCapture(device_index, backend) + if not cap.isOpened(): + print(f"无法打开摄像头 (index={device_index})") + return + + print("开始读取帧…按 Ctrl+C 可中断") + + try: + for i in range(num_frames): + ret, frame = cap.read() + if not ret: + print(f"第 {i} 帧读取失败,退出") + break + + # 示例处理:打印帧的分辨率 + h, w = frame.shape[:2] + print(f"帧 {i+1}/{num_frames} 大小:{w}x{h}") + + # 模拟处理时间 + time.sleep(0.01) + + except KeyboardInterrupt: + print("用户中断") + finally: + cap.release() + print("摄像头已释放,程序结束") + +if __name__ == "__main__": + # 可以通过修改以下参数来指定设备号或读取帧数 + main(device_index=0, num_frames=200) + +``` + +然后执行下面的命令,运行opencv usb测试代码 + +```mk1.sh +python3 opencv_usb_test.py +``` + +![image-20260429194609500](./pic/image-20260429194609500.png) + +3.3测试opencv-python中dnn模块 + +![image-20260429194639010](./pic/image-20260429194639010.png) + +测试代码:代码中FaceDetectorYN 依赖底层的dnn模块,封装后无需前处理,效果更好,dnn_test.py + +```mk1.sh +import cv2 + +# 1. 读取图片 +image_path = "image.jpg" # 替换为你的图片路径 +img = cv2.imread(image_path) +if img is None: + print("无法加载图片") + exit(1) +orig_h, orig_w = img.shape[:2] + +# 2. 初始化 FaceDetectorYN,使用原图大小并调松参数 +detector = cv2.FaceDetectorYN.create( + model="face_detection_yunet_2023mar.onnx", + config="", + input_size=(orig_w, orig_h), # 与原图一致 + score_threshold=0.4, # 提高置信度阈值到 0.4 + nms_threshold=0.5, # NMS 阈值 + top_k=200 # 保留最多 200 个候选 +) + +# 3. 检测人脸 +_, faces = detector.detect(img) + +# 4. 后处理:剔除过小的框 +min_size = 50 # 小于 50 像素的宽高都视为噪声 +filtered = [] +if faces is not None: + for face in faces: + x, y, w, h, score = face[:5].astype(int) + # 保留宽高都不小于阈值的框 + if w >= min_size and h >= min_size: + filtered.append((x, y, w, h, score)) + +# 5. 在图像上绘制过滤后的人脸框 +for x, y, w, h, score in filtered: + cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) + cv2.putText( + img, + f"{score/100:.2f}", + (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, + 0.5, + (0, 255, 0), + 1 + ) + +# 6. 保存结果并输出检测到的人脸数量 +output_path = "output_image.jpg" +cv2.imwrite(output_path, img) +print(f"检测完成,检测到 {len(filtered)} 张人脸,结果已保存到 {output_path}") +``` + +运行以下命令进行测试: + +```mk1.sh +python3 dnn_test.py +``` + +![image-20260429194651455](./pic/image-20260429194651455.png) + +检测结果: + +![image-20260429194703200](./pic/image-20260429194703200.png) + + + +‍ diff --git a/vendor/zsks/docs/gcc/opencv/pic/image-20251013150632408.png b/vendor/zsks/docs/gcc/opencv/pic/image-20251013150632408.png index 8a388cfeb9b9c11c14cbc381728e54382c8cb187..7014a202a30a37bd0fac53d3d9b4ce272f037cfd 100755 Binary files a/vendor/zsks/docs/gcc/opencv/pic/image-20251013150632408.png and b/vendor/zsks/docs/gcc/opencv/pic/image-20251013150632408.png differ diff --git a/vendor/zsks/docs/gcc/opencv/pic/image-20251016153355942.png b/vendor/zsks/docs/gcc/opencv/pic/image-20251016153355942.png index f5d5f95bb5c5732a4f3fa9782d9c8bf932ac4bb2..1ea26bca19a3cc3b8541e25feaa278843d5f480d 100755 Binary files a/vendor/zsks/docs/gcc/opencv/pic/image-20251016153355942.png and b/vendor/zsks/docs/gcc/opencv/pic/image-20251016153355942.png differ diff --git a/vendor/zsks/docs/gcc/opencv/pic/image-20251016153418154.png b/vendor/zsks/docs/gcc/opencv/pic/image-20251016153418154.png index 764009360a2028ccb7ed14fe1d70d4e4604216f0..d2ad3025f4ffa1cd7047e536a4d25b58175a2a25 100755 Binary files a/vendor/zsks/docs/gcc/opencv/pic/image-20251016153418154.png and b/vendor/zsks/docs/gcc/opencv/pic/image-20251016153418154.png differ diff --git a/vendor/zsks/docs/gcc/opencv/pic/image-20260429194703200.png b/vendor/zsks/docs/gcc/opencv/pic/image-20260429194703200.png index 9d27dcd2266fef56c595bacf03be1515225879d2..5e08f01a31afce617253711d1c8f261fa65adb7e 100755 Binary files a/vendor/zsks/docs/gcc/opencv/pic/image-20260429194703200.png and b/vendor/zsks/docs/gcc/opencv/pic/image-20260429194703200.png differ diff --git a/vendor/zsks/docs/gcc/python/README.md b/vendor/zsks/docs/gcc/python/README.md index 15c0c712fcbfb8e30db920d08a939f84be4df09d..b9932d7ce1a2ec50c34585ee13bf5a17563680b6 100755 --- a/vendor/zsks/docs/gcc/python/README.md +++ b/vendor/zsks/docs/gcc/python/README.md @@ -30,14 +30,6 @@ cd Python-3.13.2 make -j$(nproc) && make altinstall ``` -![image-20251010143023136](pic/image-20251010143023136.png) - -![image-20251010143136574](pic/image-20251010143136574.png) - -![image-20251010143226900](pic/image-20251010143226900.png) - -![image-20251010143640847](pic/image-20251010143640847.png) - ## 3.安装依赖软件 @@ -123,12 +115,6 @@ make CC="${TOOLCHAIN_BIN}/${CROSS_PREFIX}-gcc --sysroot=${SYSROOT}" -j$(nproc) make install ``` -![image-20251009173438071](pic/image-20251009173438071.png) - -![image-20251009173659012](pic/image-20251009173659012.png) - -![image-20251009174036856](pic/image-20251009174036856.png) - ![image-20260429153601363](./pic/image-20260429153601363.png) ### 3、autoconf的交叉编译 @@ -171,7 +157,7 @@ apt-get install automake libtool -y ./autogen.sh ``` -![image-20251009174843560](pic/image-20251009174843560.png) + ![image-20251009174953996](pic/image-20251009174953996.png) @@ -194,10 +180,6 @@ make -j$(nproc) make install ``` -![image-20251009175706346](pic/image-20251009175706346.png) - -![image-20251009175825681](pic/image-20251009175825681.png) - ![image-20251009175854834](pic/image-20251009175854834.png) ![image-20260429153701914](./pic/image-20260429153701914.png) @@ -247,12 +229,6 @@ make -j$(nproc) CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" make install ``` -![image-20251009180156789](pic/image-20251009180156789.png) - -![image-20251009180424732](pic/image-20251009180424732.png) - -![image-20251009180446492](pic/image-20251009180446492.png) - ![image-20251009180509397](pic/image-20251009180509397.png) ![image-20260429153809443](./pic/image-20260429153809443.png) @@ -298,11 +274,7 @@ make -j$(nproc) CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" make install ``` -![image-20251009181033404](pic/image-20251009181033404.png) - -![image-20251009181219093](pic/image-20251009181219093.png) -![image-20251009181250942](pic/image-20251009181250942.png) ![image-20251009181318999](pic/image-20251009181318999.png) diff --git a/vendor/zsks/docs/gcc/python/pic/image-20251009171921919.png b/vendor/zsks/docs/gcc/python/pic/image-20251009171921919.png index 7896aea248c4b1f73eefa3fc963b2dee3780dc65..98bc5447335e7f8d87145ef7d95b54784bdaa7ab 100755 Binary files a/vendor/zsks/docs/gcc/python/pic/image-20251009171921919.png and b/vendor/zsks/docs/gcc/python/pic/image-20251009171921919.png differ diff --git a/vendor/zsks/docs/gcc/python/pic/image-20251009200013989.png b/vendor/zsks/docs/gcc/python/pic/image-20251009200013989.png index 1256aca756ed2b3604132215e1f12b37ce67cccc..02b07f9e5f0da6cbd0e6e707c2a942992319f68d 100755 Binary files a/vendor/zsks/docs/gcc/python/pic/image-20251009200013989.png and b/vendor/zsks/docs/gcc/python/pic/image-20251009200013989.png differ diff --git a/vendor/zsks/docs/gcc/python/pic/image-20251009202143477.png b/vendor/zsks/docs/gcc/python/pic/image-20251009202143477.png index 12d778905520fd6a1b734edf450d9977677c9c24..7477f6fc392c6beb9ffba2517032c061c60e1429 100755 Binary files a/vendor/zsks/docs/gcc/python/pic/image-20251009202143477.png and b/vendor/zsks/docs/gcc/python/pic/image-20251009202143477.png differ diff --git a/vendor/zsks/docs/gcc/python/pic/image-20251009202450693.png b/vendor/zsks/docs/gcc/python/pic/image-20251009202450693.png index 08e1430c7f30533da40714205d12fd88a075e23f..9bdd392bcf03705bef4473f2820d8c02c865d8fe 100755 Binary files a/vendor/zsks/docs/gcc/python/pic/image-20251009202450693.png and b/vendor/zsks/docs/gcc/python/pic/image-20251009202450693.png differ diff --git a/vendor/zsks/docs/gcc/python/pic/image-20251010094441549.png b/vendor/zsks/docs/gcc/python/pic/image-20251010094441549.png index e981001ec636db595d2766310bf95a49e58f3914..63e1eaef2664fcd548632148c151d55fb61a91f5 100755 Binary files a/vendor/zsks/docs/gcc/python/pic/image-20251010094441549.png and b/vendor/zsks/docs/gcc/python/pic/image-20251010094441549.png differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172518811.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172518811.png" deleted file mode 100755 index 6333b0c59b20648b7780066e6bd44936028dd634..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172518811.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172549422.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172549422.png" deleted file mode 100755 index 16040c9290f4c1748c2e0683439864f0539fc90e..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172549422.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172640239.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172640239.png" deleted file mode 100755 index 3d8a25488bf13692ceff46153bfc608e542d936b..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172640239.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172810395.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172810395.png" deleted file mode 100755 index fdddb0a4dc2f9d24ce33a1567021d4951da8b46a..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507172810395.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507204206481.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507204206481.png" deleted file mode 100755 index 37fe0cb72a758ef21ab6d91afffed9cacaeb3ced..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260507204206481.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210706895.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210706895.png" deleted file mode 100755 index 93cd27ed42cd050fcf3b35adff8681667b0da43f..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210706895.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210949101.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210949101.png" deleted file mode 100755 index 6835a9f0ceec820e712b87159f0ee137491580b7..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513210949101.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513211022712.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513211022712.png" deleted file mode 100755 index c927a4e00caebac2133c375c10118b0b61e86f8c..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513211022712.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212231705.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212231705.png" deleted file mode 100755 index 3a5d82deb8f74c5eb409f1e7793b172d44b7220a..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212231705.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212351925.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212351925.png" deleted file mode 100755 index 03df57edb8c02ae2fdcb19b9150b448258008c27..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260513212351925.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095432164.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095432164.png" deleted file mode 100755 index 186ec2e7a27b5b8209e87e249b5a483149a25dca..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095432164.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095549552.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095549552.png" deleted file mode 100755 index db07dca31a6d7358a3e8216c42875a5f6be92d70..0000000000000000000000000000000000000000 Binary files "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260514095549552.png" and /dev/null differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151035611.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151035611.png" new file mode 100755 index 0000000000000000000000000000000000000000..59189c08692b0292b23abe384a5e836ca9ac6d20 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151035611.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151054326.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151054326.png" new file mode 100755 index 0000000000000000000000000000000000000000..414c25ec8445e7cc0232b25dfc1129263342f904 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519151054326.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519160927592.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519160927592.png" new file mode 100755 index 0000000000000000000000000000000000000000..dcc53a6c8612e856b329e575f140a33158071c9f Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519160927592.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162041752.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162041752.png" new file mode 100755 index 0000000000000000000000000000000000000000..9cf4ca32d70d9a037c0af9f9d43c8350c3d2de22 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162041752.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162119814.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162119814.png" new file mode 100755 index 0000000000000000000000000000000000000000..210553b1c74f1afbb8e4ae6448b424c6d69739c8 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162119814.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162223068.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162223068.png" new file mode 100755 index 0000000000000000000000000000000000000000..fe6b13ca384a8139d6a072513aa5b69ca01667b6 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519162223068.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519164931962.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519164931962.png" new file mode 100755 index 0000000000000000000000000000000000000000..dccce550c085f98bb1a41111c3864329dd1ada60 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519164931962.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165201502.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165201502.png" new file mode 100755 index 0000000000000000000000000000000000000000..06269290a30fe2cf366488e91c12b402cdf62674 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165201502.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165300704.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165300704.png" new file mode 100755 index 0000000000000000000000000000000000000000..856100c1c14d192fa7b84c6b66737598ed76ff8e Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165300704.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165326164.png" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165326164.png" new file mode 100755 index 0000000000000000000000000000000000000000..e15ee5c90cc0f1cf99080630dc6d5c72fd6ae394 Binary files /dev/null and "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/pic/image-20260519165326164.png" differ diff --git "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" index 8cdb7ce485c9c7e2a9c58d697a6887ce6ef42174..f459d39bb455a7688e68562dae7e1d717cf67363 100755 --- "a/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" +++ "b/vendor/zsks/docs/gcc/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272/ubuntu\347\263\273\347\273\237\351\225\234\345\203\217\346\236\204\345\273\272\346\214\207\345\215\227.md" @@ -55,8 +55,6 @@ git submodule init git submodule update platform/ss928v100_gcc ``` -![image-20260513210706895](pic/image-20260513210706895.png) - * 访问百度网盘链接,下载第三方软件至你的服务器的家目录目录: https://pan.baidu.com/s/1N6NVyztOJdBMSoblnlGDXg 提取码: 2awe * 在容器的命令行终端执行下面的命令,把第三方软件复制到对应目录下 @@ -69,8 +67,6 @@ cp ~/arm-trusted-firmware-2.2.tar.gz ~/pegasus/platform/ss928v100_gcc/open_ cp ~/u-boot-2020.01.tar.bz2 ~/pegasus/platform/ss928v100_gcc/open_source/u-boot ``` -![image-20260513210949101](pic/image-20260513210949101.png) - ### 步骤2:安装交叉编译链 - 点击[这里](https://gitee.com/openeuler/yocto-meta-openeuler/releases),按照下图下载0.1.8的arm64版本的所有压缩包。 @@ -90,8 +86,6 @@ tar -xzvf openeuler_gcc_arm64le.tar.gz rm -rf openeuler_gcc_arm64le.tar.gz ``` -![image-20260513211022712](pic/image-20260513211022712.png) - - 此时交叉编译工具链的可执行文件在`openeuler_gcc_arm64le/bin/`下。 ![image-20260513211102880](pic/image-20260513211102880.png) @@ -158,8 +152,6 @@ make LLVM=0 BOOT_MEDIA=emmc CHIP=ss928v100 all make BOOT_MEDIA=emmc gslboot_build -j 20 ``` - ![image-20260507172518811](pic/image-20260507172518811.png) - * 单编kernel * 进入`~/pegasus/platform/ss928v100_gcc/osdrv`,执行编译命令,编译生成的镜像位于 osdrv/pub/xxx 目录下。 @@ -168,8 +160,6 @@ make LLVM=0 BOOT_MEDIA=emmc CHIP=ss928v100 all make LLVM=0 BOOT_MEDIA=emmc atf -j 20 ``` -![image-20260507172549422](pic/image-20260507172549422.png) - ### 步骤5:编译ko - 进入`~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/obj`,执行编译命令,生成的ko文件在`~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/ko`目录下。 @@ -180,8 +170,6 @@ cd ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/obj make ``` -![image-20260507172640239](pic/image-20260507172640239.png) - ![image-20260507172725771](pic/image-20260507172725771.png) ### 步骤6:编译SDK的sample案例 @@ -194,8 +182,6 @@ cd ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/sample make ``` -![image-20260507172810395](pic/image-20260507172810395.png) - ## 3、制作Ubuntu文件系统 * **如果你需要桌面版本的,请参考3.1章节,如果不需要桌面版本的,请参考3.2章节** @@ -230,8 +216,6 @@ sudo cp -a /usr/bin/qemu-aarch64-static rootfs_desktop/usr/bin/ sudo cp -b /etc/resolv.conf rootfs_desktop/etc/resolv.conf ``` -![image-20260513212231705](pic/image-20260513212231705.png) - #### 步骤3:进入Ubuntu虚拟环境安装基础系统软件 * 在服务器的命令行终端,执行下面的命令,挂载文件系统, @@ -248,8 +232,6 @@ sudo mount -o bind /dev rootfs_desktop/dev sudo mount -o bind /dev/pts rootfs_desktop/dev/pts ``` -![image-20260513212351925](pic/image-20260513212351925.png) - * 以root角色进入Ubuntu虚拟环境(后续部署到板端的),并安装基础的系统软件 ```sh @@ -300,7 +282,7 @@ apt install -y ca-certificates update-ca-certificates --fresh sed -i 's|http://mirrors.aliyun.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list -apt update && apt upgrade -y && apt-get install -y init udev fbset sudo nano kmod net-tools ethtool ifupdown rsyslog htop iputils-ping ssh resolvconf v4l-utils wpasupplicant nfs-common busybox openbsd-inetd telnetd network-manager nfs-kernel-server && apt-get install -y xfce4 lightdm lightdm-gtk-greeter xfce4-goodies thunar xfce4-terminal +apt update && apt upgrade -y && apt-get install -y init udev fbset sudo nano kmod net-tools ethtool ifupdown rsyslog htop iputils-ping ssh resolvconf v4l-utils wpasupplicant nfs-common busybox openbsd-inetd telnetd network-manager nfs-kernel-server && apt-get install -y xfce4 lightdm lightdm-gtk-greeter xfce4-goodies thunar xfce4-terminal alsa-utils python3-opencv ffmpeg ln -s lib lib64 ``` @@ -331,9 +313,9 @@ chown -R root:root /etc/sudoers.d chown root:root /etc/sudoers passwd root - +#输出密码:root passwd zsks - +#输入密码:zsks apt-get clean ``` @@ -388,6 +370,30 @@ sleep 3 systemctl start lightdm ``` +* 添加libcamera配置 + +~~~bash +# 创建 libcamera 环境变量配置文件 +echo 'export LIBCAMERA_IPA_MODULE_PATH=/usr/lib/libcamera/ipa' > /etc/profile.d/libcamera.sh +chmod +x /etc/profile.d/libcamera.sh + +# 将 zsks 用户加入 video 用户组 +usermod -aG video zsks + +# 创建 udev 规则,开放摄像头设备权限 +cat < /etc/udev/rules.d/99-camera-perm.rules +SUBSYSTEM=="media", GROUP="video", MODE="0660" +SUBSYSTEM=="video4linux", GROUP="video", MODE="0660" +EOFs + +# 4. 确保 udev 服务开机自启 +systemctl enable systemd-udevd +~~~ + +![image-20260519151035611](./pic/image-20260519151035611.png) + +![image-20260519151054326](./pic/image-20260519151054326.png) + * 启动服务 ```sh @@ -396,9 +402,7 @@ chmod 777 /usr/bin/zsks_autorun.sh systemctl enable autorun.service ``` -![image-20260507204206481](pic/image-20260507204206481.png) - -#### 步骤5:退出Ubuntu虚拟环境 +#### 步骤4:退出Ubuntu虚拟环境 * 在编译服务器的命令行终端,执行下面的命令,退出Ubuntu虚拟环境,并卸载刚挂载的文件目录。 @@ -414,11 +418,10 @@ sudo umount rootfs_desktop/dev/pts sudo umount rootfs_desktop/dev ``` -![image-20260514095432164](pic/image-20260514095432164.png) - -#### 步骤6:依赖至文件系统 +#### 步骤5:依赖至文件系统 * 在服务器的命令行执行下面的命令,拷贝ko、so、可执行文件至文件系统 +* 注意:可参考[链接](https://gitee.com/HiSpark/pegasus/blob/master/vendor/zsks/docs/gcc/libcamera/README.md)获取制作libcamera_install的方法。 ```sh cp ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/* rootfs_desktop/usr/lib/ -rf @@ -428,19 +431,27 @@ cp ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/ko rootfs_desktop/ - cp ~/pegasus/vendor/zsks/patch/gcc/ss928_fb_tool rootfs_desktop/usr/bin/ cp ~/pegasus/vendor/zsks/patch/gcc/load_ss928v100_ubuntu rootfs_desktop/ko/ +# 1. 拷贝 libcamera 的库文件 (.so) +cp ~/libcamera_install/lib/* rootfs_desktop/usr/lib/ -rf + +# 2. 拷贝 libcamera 的可执行文件 (bin) +cp ~/libcamera_install/bin/* rootfs_desktop/usr/bin/ -rf + +#3.赋予 cam 及相关工具可执行权限 +chmod +x rootfs_desktop/usr/bin/cam +chmod +x rootfs_desktop/usr/bin/libcamera-* + chmod 777 rootfs_desktop/usr/bin/ss928_fb_tool ``` -![image-20260514095549552](pic/image-20260514095549552.png) - -#### 步骤7、打包文件系统 +#### 步骤6、打包文件系统 * 在服务器的命令行执行下面的命令,将rootfs打包成文件系统 * 注意:本文的路径可能与你的不同,请自行修改调整 ```sh -# 备注:(6291456 = 3G*1024 *1024 * 1024 / 512) -dd if=/dev/zero of=rootfs.img bs=512 count=6291456 +# 备注: 修改为 4GB 镜像 (8388608 = 4G*1024*1024*1024 / 512) +dd if=/dev/zero of=rootfs.img bs=512 count=8388608 # 下面的命令都一致 mkfs.ext4 rootfs.img @@ -456,6 +467,8 @@ sync sudo umount rootfs_ubuntu24.04_desktop ``` + + ### 3.2、制作无桌面的Ubuntu文件系统 #### 步骤1:下载并解压Ubuntu文件系统 @@ -467,13 +480,11 @@ cd ~/pegasus/os/Ubuntu/ wget https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/ubuntu-base-24.04.4-base-arm64.tar.gz -mkdir rootfs_desktop +mkdir rootfs_nodesktop -tar -zxvf ubuntu-base-24.04.4-base-arm64.tar.gz -C rootfs_desktop/ +tar -zxvf ubuntu-base-24.04.4-base-arm64.tar.gz -C rootfs_nodesktop/ ``` -![image-20260513212029115](pic/image-20260513212029115.png) - #### 步骤2:安装arm64模拟组件 * 在服务器的命令行终端,执行下面的命令,安装arm64模拟组件 @@ -495,22 +506,20 @@ sudo cp -b /etc/resolv.conf rootfs_nodesktop/etc/resolv.conf ```sh # 将编译服务器与Ubuntu虚拟环境的相关目录进行挂载 -sudo mount -t proc /proc rootfs_desktop/proc +sudo mount -t proc /proc rootfs_nodesktop/proc -sudo mount -t sysfs /sys rootfs_desktop/sys +sudo mount -t sysfs /sys rootfs_nodesktop/sys -sudo mount -o bind /dev rootfs_desktop/dev +sudo mount -o bind /dev rootfs_nodesktop/dev -sudo mount -o bind /dev/pts rootfs_desktop/dev/pts +sudo mount -o bind /dev/pts rootfs_nodesktop/dev/pts ``` -![image-20260513212351925](pic/image-20260513212351925.png) - * 以root角色进入Ubuntu虚拟环境(后续部署到板端的),并安装基础的系统软件 ```sh # 以root角色进入Ubuntu虚拟环境 -sudo chroot rootfs_desktop/ /bin/bash +sudo chroot rootfs_nodesktop/ /bin/bash chmod 777 tmp @@ -521,14 +530,16 @@ echo "127.0.0.1 localhost " > /etc/hosts apt update && apt upgrade -y && apt install vim -y cp /etc/apt/sources.list /etc/apt/sources.list_back - -vim /etc/apt/sources.list ``` -![image-20260513212512170](pic/image-20260513212512170.png) +![image-20260519162041752](./pic/image-20260519162041752.png) * 配置下载源,将/etc/apt/sources.list中的内容修改为下方的下载源 +~~~bash +vim /etc/apt/sources.list +~~~ + ```sh deb https://mirrors.aliyun.com/ubuntu-ports/ noble main restricted universe multiverse deb-src https://mirrors.aliyun.com/ubuntu-ports/ noble main restricted universe multiverse @@ -554,14 +565,18 @@ apt clean && apt update apt install -y ca-certificates update-ca-certificates --fresh +``` +![image-20260519162119814](./pic/image-20260519162119814.png) + +~~~bash sed -i 's|http://mirrors.aliyun.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list -apt update && apt upgrade -y && apt-get install -y init udev fbset sudo nano kmod net-tools ethtool ifupdown rsyslog htop iputils-ping ssh resolvconf v4l-utils wpasupplicant nfs-common busybox openbsd-inetd telnetd network-manager nfs-kernel-server && apt-get install -y xfce4 lightdm lightdm-gtk-greeter xfce4-goodies thunar xfce4-terminal +apt update && apt upgrade -y && apt-get install -y init udev fbset sudo nano kmod net-tools ethtool ifupdown rsyslog htop iputils-ping ssh resolvconf v4l-utils wpasupplicant nfs-common busybox openbsd-inetd telnetd network-manager nfs-kernel-server && apt-get install -y alsa-utils python3-opencv ffmpeg ln -s lib lib64 -``` +~~~ -![image-20260508180755330](pic/image-20260508180755330.png) +![image-20260519162223068](./pic/image-20260519162223068.png) * 新增用户,并配置相关文件的权限 @@ -587,14 +602,18 @@ chown -R root:root /etc/sudoers.d chown root:root /etc/sudoers passwd root - +#输出密码:root passwd zsks - +#输入密码:zsks apt-get clean ``` * 创建一个/usr/lib/systemd/system/autorun.service服务,并把下面的内容复制进去 +~~~bash +vi /usr/lib/systemd/system/autorun.service +~~~ + ```sh #start [Unit] @@ -615,6 +634,10 @@ WantedBy=multi-user.target * 创建一个/usr/bin/zsks_autorun.sh脚本,并把下面的内容复制进去 +~~~bash +vi /usr/bin/zsks_autorun.sh +~~~ + ```sh #!/bin/bash @@ -636,9 +659,36 @@ fi cd /ko bash load_ss928v100_ubuntu -i +ss928_fb_tool & ldconfig ``` +![image-20260519165201502](./pic/image-20260519165201502.png) + +* 添加libcamera配置 + +~~~bash +# 创建 libcamera 环境变量配置文件 +echo 'export LIBCAMERA_IPA_MODULE_PATH=/usr/lib/libcamera/ipa' > /etc/profile.d/libcamera.sh +chmod +x /etc/profile.d/libcamera.sh + +# 将 zsks 用户加入 video 用户组 +usermod -aG video zsks + +# 创建 udev 规则,开放摄像头设备权限 +cat < /etc/udev/rules.d/99-camera-perm.rules +SUBSYSTEM=="media", GROUP="video", MODE="0660" +SUBSYSTEM=="video4linux", GROUP="video", MODE="0660" +EOF + +# 4. 确保 udev 服务开机自启 +systemctl enable systemd-udevd +~~~ + +![image-20260519165326164](./pic/image-20260519165326164.png) + +![image-20260519165300704](./pic/image-20260519165300704.png) + * 启动服务 ```sh @@ -647,8 +697,6 @@ chmod 777 /usr/bin/zsks_autorun.sh systemctl enable autorun.service ``` -![image-20260507204206481](pic/image-20260507204206481.png) - #### 步骤4:退出Ubuntu虚拟环境 * 在编译服务器的命令行终端,执行下面的命令,退出Ubuntu虚拟环境,并卸载刚挂载的文件目录。 @@ -656,20 +704,19 @@ systemctl enable autorun.service ```sh exit -sudo umount rootfs_desktop/proc +sudo umount rootfs_nodesktop/proc -sudo umount rootfs_desktop/sys +sudo umount rootfs_nodesktop/sys -sudo umount rootfs_desktop/dev/pts +sudo umount rootfs_nodesktop/dev/pts -sudo umount rootfs_desktop/dev +sudo umount rootfs_nodesktop/dev ``` -![image-20260514095432164](pic/image-20260514095432164.png) - #### 步骤5:依赖至文件系统 * 在服务器的命令行执行下面的命令,拷贝ko、so、可执行文件至文件系统 +* 注意:可参考[链接](https://gitee.com/HiSpark/pegasus/blob/master/vendor/zsks/docs/gcc/libcamera/README.md)获取制作libcamera_install的方法。 ```sh cp ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/* rootfs_nodesktop/usr/lib/ -rf @@ -677,6 +724,16 @@ cp ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/lib/* rootfs_nodeskto cp ~/pegasus/platform/ss928v100_gcc/smp/a55_linux/mpp/out/ko rootfs_nodesktop/ -rf cp ~/pegasus/vendor/zsks/patch/gcc/load_ss928v100_ubuntu rootfs_nodesktop/ko/ + +# 1. 拷贝 libcamera 的库文件 (.so) +cp ~/libcamera_install/lib/* rootfs_nodesktop/usr/lib/ -rf + +# 2. 拷贝 libcamera 的可执行文件 (bin) +cp ~/libcamera_install/bin/* rootfs_nodesktop/usr/bin/ -rf + +#3.赋予 cam 及相关工具可执行权限 +chmod +x rootfs_nodesktop/usr/bin/cam +chmod +x rootfs_nodesktop/usr/bin/libcamera-* ``` #### 步骤6、打包文件系统 @@ -685,15 +742,14 @@ cp ~/pegasus/vendor/zsks/patch/gcc/load_ss928v100_ubuntu rootfs_nodesktop/ko/ * 注意:本文的路径可能与你的不同,请自行修改调整 ```sh -# 备注:(2,097,152 = 1G*1024 *1024 * 1024 / 512) -dd if=/dev/zero of=rootfs.img bs=512 count=2097152 - +# 备注:(4194304 = 2G*1024 *1024 * 1024 / 512) +dd if=/dev/zero of=rootfs_nodesk.img bs=512 count=4194304 # 下面的命令都一致 -mkfs.ext4 rootfs.img +mkfs.ext4 rootfs_nodesk.img mkdir rootfs_ubuntu24.04_nodesktop -mount rootfs.img rootfs_ubuntu24.04_nodesktop +sudo mount rootfs_nodesk.img rootfs_ubuntu24.04_nodesktop cp -a rootfs_nodesktop/* rootfs_ubuntu24.04_nodesktop/ diff --git a/vendor/zsks/patch/clang/0001-support-USB-Camera-and-mipi-camera.patch b/vendor/zsks/patch/clang/0001-support-USB-Camera-and-mipi-camera.patch new file mode 100755 index 0000000000000000000000000000000000000000..c7681102383d8bb0e76e4919a37b56b173c506eb --- /dev/null +++ b/vendor/zsks/patch/clang/0001-support-USB-Camera-and-mipi-camera.patch @@ -0,0 +1,1701 @@ +From 3eaca2c56010ba5d7964db79c06d7042b5204488 Mon Sep 17 00:00:00 2001 +From: wgm <1480559020@qq.com> +Date: Tue, 19 May 2026 15:52:23 +0800 +Subject: [PATCH] support-USB-Camera-and-mipi-camera + +diff --git a/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h b/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h +index 03f7ccf..3b72e7d 100644 +--- a/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h ++++ b/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h +@@ -78,6 +78,11 @@ typedef struct { + } ot_isp_sns_obj; + + extern ot_isp_sns_obj g_sns_hy_s0603_obj; ++extern ot_isp_sns_obj g_sns_os08a20_obj; ++extern ot_isp_sns_obj g_sns_imx347_slave_obj; ++extern ot_isp_sns_obj g_sns_os04a10_obj; ++extern ot_isp_sns_obj g_sns_sc450ai_obj; ++extern ot_isp_sns_obj g_sns_sc450ai_2l_obj; + + #define sensor_check_pointer_return(ptr) \ + do { \ +diff --git a/smp/a55_linux/mpp/sample/Makefile.param b/smp/a55_linux/mpp/sample/Makefile.param +index 88aead8..f8a51a1 100644 +--- a/smp/a55_linux/mpp/sample/Makefile.param ++++ b/smp/a55_linux/mpp/sample/Makefile.param +@@ -7,44 +7,56 @@ endif + ################# select sensor type for your sample ############################### + #### HY_S0603_MIPI_8M_30FPS_12BIT ################# + #### HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1 ################# +- ++#### OV_OS08A20_MIPI_8M_30FPS_12BIT ################# ++#### OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1 ################# ++#### SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT ################# ++#### OV_OS04A10_MIPI_4M_30FPS_12BIT ################# ++#### SC450AI_MIPI_4M_30FPS_10BIT ################# ++#### SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1 ################# ++#### SC450AI_2L_MIPI_4M_30FPS_10BIT ################# ++#### SC450AI_2L_MIPI_2M_30FPS_10BIT ################# ++#### SC450AI_2L_MIPI_1344x760_30FPS_10BIT ################# + ## change sensor type here. default: hy_s0603 + +-SENSOR0_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR1_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR2_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR3_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT ++SENSOR0_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR1_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR2_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR3_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT + +-MPI_LIBS := $(REL_LIB)/libss_mpi.so ++MPI_LIBS := -lss_mpi + + ifeq ($(CONFIG_OT_ISP_SUPPORT), y) +-MPI_LIBS += $(REL_LIB)/libss_ae.so +-MPI_LIBS += $(REL_LIB)/libss_isp.so +-MPI_LIBS += $(REL_LIB)/libot_isp.so +-MPI_LIBS += $(REL_LIB)/libss_awb.so +-MPI_LIBS += $(REL_LIB)/libss_dehaze.so +-MPI_LIBS += $(REL_LIB)/libss_extend_stats.so +-MPI_LIBS += $(REL_LIB)/libss_drc.so +-MPI_LIBS += $(REL_LIB)/libss_ldci.so +-MPI_LIBS += $(REL_LIB)/libss_crb.so +-MPI_LIBS += $(REL_LIB)/libss_bnr.so +-MPI_LIBS += $(REL_LIB)/libss_calcflicker.so +-MPI_LIBS += $(REL_LIB)/libss_ir_auto.so +-MPI_LIBS += $(REL_LIB)/libss_acs.so +-MPI_LIBS += $(REL_LIB)/libsns_hy_s0603.so +- ++MPI_LIBS += -lss_ae ++MPI_LIBS += -lss_isp ++MPI_LIBS += -lot_isp ++MPI_LIBS += -lss_awb ++MPI_LIBS += -lss_dehaze ++MPI_LIBS += -lss_extend_stats ++MPI_LIBS += -lss_drc ++MPI_LIBS += -lss_ldci ++MPI_LIBS += -lss_crb ++MPI_LIBS += -lss_bnr ++MPI_LIBS += -lss_calcflicker ++MPI_LIBS += -lss_ir_auto ++MPI_LIBS += -lss_acs ++MPI_LIBS += -lsns_hy_s0603 ++MPI_LIBS += -lsns_os08a20 ++MPI_LIBS += -lsns_imx347_slave ++MPI_LIBS += -lsns_os04a10 ++MPI_LIBS += -lsns_sc450ai ++MPI_LIBS += -lsns_sc450ai_2l + endif + + + ifeq ($(CONFIG_OT_AUDIO_SUPPORT), y) +-AUDIO_LIBA := $(REL_LIB)/libss_voice_engine.so +-AUDIO_LIBA += $(REL_LIB)/libss_upvqe.so +-AUDIO_LIBA += $(REL_LIB)/libss_dnvqe.so +-AUDIO_LIBA += $(REL_LIB)/libaac_comm.so +-AUDIO_LIBA += $(REL_LIB)/libaac_enc.so +-AUDIO_LIBA += $(REL_LIB)/libaac_dec.so +-AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.so +-AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.so ++AUDIO_LIBA := -lss_voice_engine ++AUDIO_LIBA += -lss_upvqe ++AUDIO_LIBA += -lss_dnvqe ++AUDIO_LIBA += -laac_comm ++AUDIO_LIBA += -laac_enc ++AUDIO_LIBA += -laac_dec ++AUDIO_LIBA += -laac_sbr_enc ++AUDIO_LIBA += -laac_sbr_dec + endif + + COMMON_DIR ?= $(PWD)/../common +@@ -103,22 +115,22 @@ AUDIO_MODULE_LIB_TYPE ?= AUDIO_LIB_TYPE_STATIC + ifeq ($(AUDIO_MODULE_LIB_TYPE), AUDIO_LIB_TYPE_STATIC) + ##### VQE ##### + CFLAGS += -DOT_VQE_USE_STATIC_MODULE_REGISTER +- AUDIO_LIBA += $(REL_LIB)/libvqe_res.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_record.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_hpf.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_anr.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_aec.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_agc.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_eq.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_talkv2.so ++ AUDIO_LIBA += -lvqe_res ++ AUDIO_LIBA += -lvqe_record ++ AUDIO_LIBA += -lvqe_hpf ++ AUDIO_LIBA += -lvqe_anr ++ AUDIO_LIBA += -lvqe_aec ++ AUDIO_LIBA += -lvqe_agc ++ AUDIO_LIBA += -lvqe_eq ++ AUDIO_LIBA += -lvqe_talkv2 + ##### AAC ##### + CFLAGS += -DOT_AAC_USE_STATIC_MODULE_REGISTER +- AUDIO_LIBA += $(REL_LIB)/libaac_dec.so +- AUDIO_LIBA += $(REL_LIB)/libaac_enc.so +- AUDIO_LIBA += $(REL_LIB)/libaac_comm.so ++ AUDIO_LIBA += -laac_dec ++ AUDIO_LIBA += -laac_enc ++ AUDIO_LIBA += -laac_comm + CFLAGS += -DOT_AAC_HAVE_SBR_LIB +- AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.so +- AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.so ++ AUDIO_LIBA += -laac_sbr_dec ++ AUDIO_LIBA += -laac_sbr_enc + endif + endif + +@@ -127,7 +139,7 @@ GYRO_DIS ?= n + + ifeq ($(GYRO_DIS), y) + CFLAGS += -DOT_GYRODIS_SUPPORT +- MPI_LIBS += $(REL_LIB)/libss_motionfusion.so ++ MPI_LIBS += -lss_motionfusion + endif + + ######################################################################### +@@ -167,9 +179,8 @@ MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/ipcmsg/include + MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/datafifo/include + + ifeq ($(CONFIG_DRIVER_SPACE_TYPE),user_space) +-MPI_LIBS += $(REL_LIB)/svp_npu/libsvp_acl.so +-MPI_LIBS += -L$(REL_LIB)/svp_npu -lprotobuf-c +-SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/extdrv ++MPI_LIBS += -lsvp_acl -lprotobuf-c ++SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/svp_npu + SDK_LIB := $(SDK_LIB_PATH) + SDK_LIB += -l$(KO_PREFIX)_osal + SDK_LIB += -l$(KO_PREFIX)_base +@@ -192,16 +203,16 @@ SDK_LIB += -l$(KO_PREFIX)_vi + SDK_LIB += -l$(KO_PREFIX)_mpi_isp + SDK_LIB += -l$(KO_PREFIX)_rc + SDK_LIB += -l$(KO_PREFIX)_jpegd +-SDK_LIB += $(REL_LIB)/libss_hdmi.so ++SDK_LIB += -lss_hdmi + SDK_LIB += -l$(KO_PREFIX)_vfmw + SDK_LIB += -l$(KO_PREFIX)_gdc + SDK_LIB += -l$(KO_PREFIX)_dis + SDK_LIB += -l$(KO_PREFIX)_irq +-SDK_LIB += $(REL_LIB)/libss_dpu_match.so +-SDK_LIB += $(REL_LIB)/libss_dpu_rect.so +-SDK_LIB += $(REL_LIB)/libss_mau.so +-SDK_LIB += $(REL_LIB)/libss_ive.so +-SDK_LIB += $(REL_LIB)/libss_pqp.so ++SDK_LIB += -lss_dpu_match ++SDK_LIB += -lss_dpu_rect ++SDK_LIB += -lss_mau ++SDK_LIB += -lss_ive ++SDK_LIB += -lss_pqp + #SDK_LIB += -l$(KO_PREFIX)_avs + # SDK_LIB += -l$(KO_PREFIX)_mcf + # SDK_LIB += -l$(KO_PREFIX)_mcf_vi +diff --git a/smp/a55_linux/mpp/sample/common/Makefile b/smp/a55_linux/mpp/sample/common/Makefile +index 502ec11..3c5db63 100644 +--- a/smp/a55_linux/mpp/sample/common/Makefile ++++ b/smp/a55_linux/mpp/sample/common/Makefile +@@ -1,6 +1,8 @@ + param_file=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))/../Makefile.param + include $(param_file) + ++CFLAGS += -fPIC ++ + .PHONY : clean all + all:$(COMM_OBJ) + +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm.h b/smp/a55_linux/mpp/sample/common/sample_comm.h +index 10c8cbd..c8a96e5 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm.h ++++ b/smp/a55_linux/mpp/sample/common/sample_comm.h +@@ -232,6 +232,15 @@ typedef enum { + typedef enum { + HY_S0603_MIPI_8M_30FPS_12BIT, + HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1, ++ OV_OS08A20_MIPI_8M_30FPS_12BIT, ++ OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1, ++ OV_OS04A10_MIPI_4M_30FPS_12BIT, ++ OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1, ++ SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT, ++ SC450AI_MIPI_4M_30FPS_10BIT, ++ SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1, ++ SC450AI_2L_MIPI_4M_30FPS_10BIT, ++ SC450AI_2L_MIPI_2M_30FPS_10BIT, + SNS_TYPE_BUTT, + } sample_sns_type; + +@@ -538,6 +547,12 @@ typedef struct { + td_u64 last_time; + td_u64 time_gap; + td_u64 fps; ++# ifdef USE_USB_CAMERA ++ td_char *v4l2_device; ++ td_u32 width; ++ td_u32 height; ++ td_u32 pixel_format; ++# endif + } vdec_thread_param; + + typedef struct { +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c +index 52d2aaf..aef5725 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c +@@ -52,8 +52,6 @@ + static ot_isp_sns_type g_sns_type[OT_VI_MAX_PIPE_NUM] = {(ot_isp_sns_type)SNS_TYPE_BUTT}; + static pthread_t g_isp_pid[OT_VI_MAX_DEV_NUM] = {0}; + +-extern ot_isp_sns_obj g_sns_hy_s0603_obj; +- + /* IspPub attr */ + static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps = { + {0, 32, 3840, 2160}, +@@ -85,6 +83,141 @@ static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps_wdr2to1 = { + }, + }; + ++static ot_isp_pub_attr g_isp_pub_attr_os08a20_mipi_8m_30fps = { ++ {0, 24, 3840, 2160}, ++ {3840, 2160}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 3840, 2180}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os08a20_mipi_8m_30fps_wdr2to1 = { ++ {0, 24, 3840, 2160}, ++ {3840, 2160}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 3840, 2180}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1 = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_imx347_slave_mipi_4m_30fps = { ++ {0, 20, WIDTH_2592, HEIGHT_1520}, ++ {WIDTH_2592, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2592, 1540}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_mipi_4m_30fps_wdr2to1 = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_2l_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_2l_mipi_2m_30fps = { ++ {0, 0, FHD_WIDTH, FHD_HEIGHT}, ++ {FHD_WIDTH, FHD_HEIGHT}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 1920, 1080}, ++ }, ++}; ++ + td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_attr *pub_attr) + { + switch (sns_type) { +@@ -96,6 +229,42 @@ td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_ + (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), + &g_isp_pub_attr_hy_s0603_mipi_8m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os08a20_mipi_8m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os08a20_mipi_8m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os04a10_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_imx347_slave_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_2l_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_2l_mipi_2m_30fps, sizeof(ot_isp_pub_attr)); ++ break; + default: + (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), + &g_isp_pub_attr_hy_s0603_mipi_8m_30fps, sizeof(ot_isp_pub_attr)); +@@ -111,6 +280,20 @@ ot_isp_sns_obj *sample_comm_isp_get_sns_obj(sample_sns_type sns_type) + case HY_S0603_MIPI_8M_30FPS_12BIT: + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + return &g_sns_hy_s0603_obj; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ return &g_sns_os08a20_obj; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ return &g_sns_os04a10_obj; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ return &g_sns_imx347_slave_obj; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ return &g_sns_sc450ai_obj; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ return &g_sns_sc450ai_2l_obj; + default: + return TD_NULL; + } +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c +index a0c9ad9..517b6d3 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c +@@ -32,6 +32,17 @@ + #include + #include "sample_comm.h" + ++#ifdef USE_USB_CAMERA ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++ + #define SEND_STREAM_CNT 5 + #define VDEC_SECOND 1000000 + #define SAMPLE_VDEC_LOW_DELAY_LINE_CNT 16 +@@ -633,6 +644,223 @@ td_s32 sample_comm_vdec_check_send_stream_param(vdec_thread_param *thread_param, + return TD_SUCCESS; + } + ++ ++#ifdef USE_USB_CAMERA ++ ++td_void *sample_comm_vdec_send_stream(td_void *args) ++{ ++ printf("vdec send stream thread start\n"); ++ ++ vdec_thread_param *thread_param = (vdec_thread_param *)args; ++ ot_vdec_stream stream; ++ printf("sample_comm_vdec_send_stream v4l2 \r\n"); ++ ++ td_s32 v4l2_fd = -1; ++ struct v4l2_capability cap; ++ struct v4l2_format fmt; ++ struct v4l2_requestbuffers req; ++ struct v4l2_buffer v4l2_buf; ++ enum v4l2_buf_type buf_type; ++ fd_set fds; ++ struct timeval tv; ++ td_u8 *v4l2_buffers[4] = {NULL}; ++ td_u32 buffer_count = 0; ++ td_u32 max_buffer_length = 0; ++ ++ prctl(PR_SET_NAME, "v4l2_to_vdec", 0, 0, 0); ++ ++ if (thread_param == NULL) { ++ sample_print("?????????!"); ++ return (td_void *)TD_FAILURE; ++ } ++ ++ sample_print("????v4l2????????: %s", thread_param->v4l2_device); ++ v4l2_fd = open(thread_param->v4l2_device, O_RDWR | O_NONBLOCK, 0); ++ if (v4l2_fd < 0) { ++ sample_print("?????????? %s: %s", ++ thread_param->v4l2_device, strerror(errno)); ++ return (td_void *)(TD_FAILURE); ++ } ++ ++ if (ioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) { ++ sample_print("VIDIOC_QUERYCAP????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { ++ sample_print("?????????????"); ++ goto v4l2_cleanup; ++ } ++ ++ memset(&fmt, 0, sizeof(fmt)); ++ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ fmt.fmt.pix.width = thread_param->width; ++ fmt.fmt.pix.height = thread_param->height; ++ fmt.fmt.pix.pixelformat = thread_param->pixel_format; ++ fmt.fmt.pix.field = V4L2_FIELD_ANY; ++ ++ if (ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt) < 0) { ++ sample_print("VIDIOC_S_FMT????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ struct v4l2_streamparm parm; ++ memset(&parm, 0, sizeof(parm)); ++ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ parm.parm.capture.timeperframe.numerator = 1; ++ parm.parm.capture.timeperframe.denominator = thread_param->fps; ++ if (ioctl(v4l2_fd, VIDIOC_S_PARM, &parm) < 0) { ++ sample_print("??????????????????: %s", strerror(errno)); ++ } ++ ++ memset(&req, 0, sizeof(req)); ++ req.count = 4; ++ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ req.memory = V4L2_MEMORY_MMAP; ++ ++ if (ioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { ++ sample_print("VIDIOC_REQBUFS????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ buffer_count = req.count; ++ max_buffer_length = 0; ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ v4l2_buf.index = i; ++ ++ if (ioctl(v4l2_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QUERYBUF????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ if (v4l2_buf.length > max_buffer_length) { ++ max_buffer_length = v4l2_buf.length; ++ } ++ ++ v4l2_buffers[i] = mmap(NULL, v4l2_buf.length, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, ++ v4l2_fd, ++ v4l2_buf.m.offset); ++ ++ if (v4l2_buffers[i] == MAP_FAILED) { ++ sample_print("mmap???: %s", strerror(errno)); ++ v4l2_buffers[i] = NULL; ++ goto v4l2_cleanup; ++ } ++ } ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ v4l2_buf.index = i; ++ ++ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QBUF????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ } ++ ++ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ if (ioctl(v4l2_fd, VIDIOC_STREAMON, &buf_type) < 0) { ++ sample_print("VIDIOC_STREAMON????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ sample_print("v4l2???????????: %s, %dx%d@%llufps, ???: %c%c%c%c", ++ thread_param->v4l2_device, ++ thread_param->width, ++ thread_param->height, ++ thread_param->fps, ++ thread_param->pixel_format & 0xFF, ++ (thread_param->pixel_format >> 8) & 0xFF, ++ (thread_param->pixel_format >> 16) & 0xFF, ++ (thread_param->pixel_format >> 24) & 0xFF); ++ ++ while (thread_param->e_thread_ctrl == THREAD_CTRL_START) { ++ FD_ZERO(&fds); ++ FD_SET(v4l2_fd, &fds); ++ ++ tv.tv_sec = 2; ++ tv.tv_usec = 0; ++ ++ td_s32 r = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); ++ if (r == -1) { ++ if (errno == EINTR) continue; ++ sample_print("select????: %s", strerror(errno)); ++ break; ++ } ++ ++ if (r == 0) { ++ sample_print("select???"); ++ continue; ++ } ++ ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ ++ if (ioctl(v4l2_fd, VIDIOC_DQBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_DQBUF????: %s", strerror(errno)); ++ continue; ++ } ++ ++ if (v4l2_buf.bytesused == 0) { ++ sample_print("????????"); ++ goto requeue_buffer; ++ } ++ ++ memset(&stream, 0, sizeof(ot_vdec_stream)); ++ stream.addr = v4l2_buffers[v4l2_buf.index]; ++ stream.len = v4l2_buf.bytesused; ++ stream.end_of_stream = TD_FALSE; ++ ++ struct timeval now; ++ gettimeofday(&now, NULL); ++ stream.pts = now.tv_sec * 1000000 + now.tv_usec; ++ ++ td_s32 s32Ret = ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, 30); ++ if (s32Ret != TD_SUCCESS) { ++ sample_print("?????VDEC???, ret=%#x", s32Ret); ++ } ++ ++requeue_buffer: ++ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QBUF????: %s", strerror(errno)); ++ break; ++ } ++ } ++ ++ memset(&stream, 0, sizeof(ot_vdec_stream)); ++ stream.end_of_stream = TD_TRUE; ++ ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, -1); ++ ++ sample_print("v4l2?????????"); ++ ++v4l2_cleanup: ++ if (v4l2_fd >= 0) { ++ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ioctl(v4l2_fd, VIDIOC_STREAMOFF, &buf_type); ++ } ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ if (v4l2_buffers[i]) { ++ munmap(v4l2_buffers[i], max_buffer_length); ++ } ++ } ++ ++ if (v4l2_fd >= 0) { ++ close(v4l2_fd); ++ } ++ ++ return (td_void *)TD_SUCCESS; ++} ++#else + td_void *sample_comm_vdec_send_stream(td_void *args) + { + vdec_thread_param *thread_param = (vdec_thread_param *)args; +@@ -691,6 +919,7 @@ end1: + path = TD_NULL; + return (td_void *)TD_SUCCESS; + } ++#endif + + td_void sample_comm_vdec_cmd_not_circle_send(td_u32 chn_num, vdec_thread_param *vdec_send, + pthread_t *vdec_thread, td_u32 send_arr_len, td_u32 thread_arr_len) +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c +index 5b66f54..8e999f6 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c +@@ -51,6 +51,7 @@ + #define MIPI_NUM 3 + #define OB_HEIGHT_END 32 + #define OB_HEIGHT_START 0 ++#define IMX347_OB_HEIGHT_END 20 + + typedef struct { + sample_vi_user_frame_info *user_frame_info; +@@ -111,6 +112,246 @@ static combo_dev_attr_t g_mipi_4lane_chn0_sensor_hy_s0603_10bit_8m_wdr2to1_attr + } + }; + ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2592, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 2, WIDTH_2592, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_dev2_attr = { ++ .devno = 2, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_dev2_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 0, /* dev0 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 2, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn1_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 1, /* dev1 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {1, 3, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn2_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 6, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn3_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 3, /* dev3 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {5, 7, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 0, /* dev0 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 2, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn1_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 1, /* dev1 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {1, 3, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn2_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 6, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn3_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 3, /* dev3 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {5, 7, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ + static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_attr_t *combo_attr) + { + td_u32 ob_height = OB_HEIGHT_START; +@@ -125,10 +366,47 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), + &g_mipi_4lane_chn0_sensor_hy_s0603_10bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ //ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; + + default: + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), +- &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); + } + combo_attr->img_rect.height = combo_attr->img_rect.height + ob_height; + } +@@ -138,9 +416,21 @@ static td_void sample_comm_vi_get_mipi_ext_data_attr(sample_sns_type sns_type, e + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), + &g_mipi_ext_data_type_12bit_8m_nowdr_attr, sizeof(ext_data_type_t)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), ++ &g_mipi_ext_data_type_default_attr, sizeof(ext_data_type_t)); ++ break; + + default: + (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), +@@ -163,7 +453,90 @@ static td_void sample_comm_vi_get_mipi_attr_by_dev_id(sample_sns_type sns_type, + &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); + } + break; +- ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ //ob_height = OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ if (vi_dev == 0) { /* dev0 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 1) { /* dev1 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn1_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn2_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 3) { /* dev3 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn3_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ if (vi_dev == 0) { /* dev0 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 1) { /* dev1 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn1_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn2_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 3) { /* dev3 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn3_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; + default: + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), + &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); +@@ -240,6 +613,23 @@ td_void sample_comm_vi_get_size_by_sns_type(sample_sns_type sns_type, ot_size *s + size->width = WIDTH_3840; + size->height = HEIGHT_2160; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ size->width = WIDTH_3840; ++ size->height = HEIGHT_2160; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ size->width = WIDTH_2688; ++ size->height = HEIGHT_1520; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ size->width = WIDTH_2592; ++ size->height = HEIGHT_1520; ++ break; + + default: + size->width = WIDTH_1920; +@@ -256,6 +646,24 @@ td_u32 sample_comm_vi_get_obheight_by_sns_type(sample_sns_type sns_type) + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + ob_height = OB_HEIGHT_END; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ ob_height = OB_HEIGHT_START; ++ break; ++ + default: + break; + } +@@ -267,8 +675,17 @@ static td_u32 sample_comm_vi_get_pipe_num_by_sns_type(sample_sns_type sns_type) + { + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + return 1; + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: + return 2; /* 2 pipe */ + + default: +@@ -280,9 +697,18 @@ static ot_wdr_mode sample_comm_vi_get_wdr_mode_by_sns_type(sample_sns_type sns_t + { + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + return OT_WDR_MODE_NONE; + + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: + return OT_WDR_MODE_2To1_LINE; + + default: +@@ -295,7 +721,7 @@ td_void sample_comm_vi_get_default_sns_info(sample_sns_type sns_type, sample_sns + sns_info->sns_type = sns_type; + sns_info->sns_clk_src = 0; + sns_info->sns_rst_src = 0; +- sns_info->bus_id = 2; /* i2c2 */ ++ sns_info->bus_id = 5; /* i2c5 */ + } + + td_void sample_comm_vi_get_default_mipi_info(sample_sns_type sns_type, sample_mipi_info *mipi_info) +diff --git a/smp/a55_linux/mpp/sample/gfbg/Makefile b/smp/a55_linux/mpp/sample/gfbg/Makefile +index c4ad611..ee7cb6e 100644 +--- a/smp/a55_linux/mpp/sample/gfbg/Makefile ++++ b/smp/a55_linux/mpp/sample/gfbg/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + SMP_SRCS := $(wildcard *.c) + TARGET := $(SMP_SRCS:%.c=%) + +-MPI_LIBS += $(REL_LIB)/libss_tde.so ++MPI_LIBS += -lss_tde + + TARGET_PATH := $(PWD) + +diff --git a/smp/a55_linux/mpp/sample/hnr/Makefile b/smp/a55_linux/mpp/sample/hnr/Makefile +index a457015..3a71a5c 100755 +--- a/smp/a55_linux/mpp/sample/hnr/Makefile ++++ b/smp/a55_linux/mpp/sample/hnr/Makefile +@@ -8,8 +8,8 @@ SMP_SRCS := $(wildcard $(PWD)/sample_hnr.c) + + ifeq ($(CONFIG_OT_ISP_HNR_SUPPORT), y) + CFLAGS += -DSAMPLE_HNR_SUPPORT +-MPI_LIBS += $(REL_LIB)/libss_pqp.so +-MPI_LIBS += $(REL_LIB)/libss_hnr.so ++MPI_LIBS += -lss_pqp ++MPI_LIBS += -lss_hnr + endif + + # compile linux or LITEOS +diff --git a/smp/a55_linux/mpp/sample/hnr/sample_hnr.c b/smp/a55_linux/mpp/sample/hnr/sample_hnr.c +index db2fabf..3df7490 100644 +--- a/smp/a55_linux/mpp/sample/hnr/sample_hnr.c ++++ b/smp/a55_linux/mpp/sample/hnr/sample_hnr.c +@@ -519,6 +519,10 @@ static td_s32 sample_hnr_start_venc_and_vo(ot_vpss_grp vpss_grp[], td_u32 grp_nu + + if (SENSOR0_TYPE == HY_S0603_MIPI_8M_30FPS_12BIT) { + g_venc_chn_param.size = PIC_3840X2160; ++ } else if (SENSOR0_TYPE == SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT) { ++ g_venc_chn_param.size = PIC_2560X1440; ++ } else if (SENSOR0_TYPE == OV_OS08A20_MIPI_8M_30FPS_12BIT) { ++ g_venc_chn_param.size = PIC_3840X2160; + } else { + g_venc_chn_param.size = PIC_1080P; + } +@@ -765,7 +769,7 @@ static td_s32 sample_hnr_set_blc(ot_vi_pipe vi_pipe, sample_sns_type sns_type) + } + } + +- if (sns_type == HY_S0603_MIPI_8M_30FPS_12BIT) { ++ if ((sns_type == HY_S0603_MIPI_8M_30FPS_12BIT) || (sns_type == SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT)) { + black_level_attr.black_level_mode = OT_ISP_BLACK_LEVEL_MODE_DYNAMIC; + } + +diff --git a/smp/a55_linux/mpp/sample/smp_linux.mak b/smp/a55_linux/mpp/sample/smp_linux.mak +index 19cd519..f07923d 100644 +--- a/smp/a55_linux/mpp/sample/smp_linux.mak ++++ b/smp/a55_linux/mpp/sample/smp_linux.mak +@@ -4,7 +4,7 @@ OBJS := $(SMP_SRCS:%.c=%.o) + + CFLAGS += $(COMM_INC) + +-MPI_LIBS += $(REL_LIB)/libss_hdmi.so ++MPI_LIBS += -lss_hdmi + MPI_LIBS += $(LIBS_LD_CFLAGS) + + .PHONY : clean all +@@ -12,7 +12,7 @@ MPI_LIBS += $(LIBS_LD_CFLAGS) + all: $(TARGET) + + $(TARGET):$(COMM_OBJ) $(OBJS) +- $(CC) $(CFLAGS) -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) $(REL_LIB)/libsecurec.so -Wl,--end-group ++ $(CC) $(CFLAGS) -L$(REL_LIB) -L$(REL_LIB)/svp_npu -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,-rpath=$$ORIGIN/../lib -Wl,-rpath-link=$(REL_LIB) -Wl,-rpath-link=$(REL_LIB)/svp_npu -Wl,--disable-new-dtags -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) -lsecurec -Wl,--end-group + + clean: + @rm -f $(TARGET_PATH)/$(TARGET) +diff --git a/smp/a55_linux/mpp/sample/snap/Makefile b/smp/a55_linux/mpp/sample/snap/Makefile +index b4d617e..f2f4324 100644 +--- a/smp/a55_linux/mpp/sample/snap/Makefile ++++ b/smp/a55_linux/mpp/sample/snap/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + ########### SRCS & INC ############ + SMP_SRCS := $(wildcard $(PWD)/*.c) + +-MPI_LIBS += $(REL_LIB)/libss_snap.so ++MPI_LIBS += -lss_snap + + TARGET := sample_snap + +diff --git a/smp/a55_linux/mpp/sample/svp/Makefile.param b/smp/a55_linux/mpp/sample/svp/Makefile.param +index 3983a2c..de8a735 100644 +--- a/smp/a55_linux/mpp/sample/svp/Makefile.param ++++ b/smp/a55_linux/mpp/sample/svp/Makefile.param +@@ -5,16 +5,15 @@ COMMON_DIR:=$(PWD)/../../common + AUDIO_ADP_DIR:=$(PWD)/../../audio/adp + include ../../Makefile.param + +-MPI_LIBS += $(REL_LIB)/libss_ive.so +-MPI_LIBS += $(REL_LIB)/libss_md.so +-MPI_LIBS += $(REL_LIB)/libss_mau.so +-MPI_LIBS += $(REL_LIB)/libss_dpu_rect.so +-MPI_LIBS += $(REL_LIB)/libss_dpu_match.so ++MPI_LIBS += -lss_ive ++MPI_LIBS += -lss_md ++MPI_LIBS += -lss_mau ++MPI_LIBS += -lss_dpu_rect ++MPI_LIBS += -lss_dpu_match + ifneq ($(CONFIG_DRIVER_SPACE_TYPE),user_space) +- MPI_LIBS += $(REL_LIB)/libss_dsp.so ++ MPI_LIBS += -lss_dsp + endif +-MPI_LIBS += $(REL_LIB)/svp_npu/libsvp_acl.so +-MPI_LIBS += -L$(REL_LIB)/svp_npu -lprotobuf-c ++MPI_LIBS += -lsvp_acl -lprotobuf-c + CFLAGS += -I$(PWD)/../common + CFLAGS += -I$(REL_INC)/svp_npu + CFLAGS += -fstack-protector-strong +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c +index 3b3b289..b2eb9d8 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c +@@ -61,6 +61,22 @@ static td_s32 sample_common_svp_get_pic_type_by_sns_type(sample_sns_type sns_typ + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + size[0] = PIC_3840X2160; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ size[0] = PIC_3840X2160; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ size[0] = PIC_2688X1520; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ size[0] = PIC_2592X1520; ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ size[0] = PIC_1080P; ++ break; + default: + size[0] = PIC_3840X2160; + break; +@@ -428,7 +444,7 @@ static td_void sample_common_svp_stop_vpss(td_s32 vpss_grp_cnt, td_u32 vpss_chn_ + } + } + +-static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) ++td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) + { + ot_rect def_disp_rect = {0, 0, 1920, 1080}; + ot_size def_img_size = {1920, 1080}; +@@ -441,7 +457,7 @@ static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) + vo_cfg->vo_dev = SAMPLE_VO_DEV_UHD; + + vo_cfg->vo_intf_type = OT_VO_INTF_HDMI; +- vo_cfg->intf_sync = OT_VO_OUT_1080P30; ++ vo_cfg->intf_sync = OT_VO_OUT_1080P60; + vo_cfg->bg_color = COLOR_RGB_BLACK; + vo_cfg->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vo_cfg->disp_rect = def_disp_rect; +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h +index 626a2d6..dd86d96 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h +@@ -60,6 +60,8 @@ typedef enum { + + typedef struct { + ot_point point[OT_POINT_NUM]; ++ td_float score; ++ td_u16 class_id; + } ot_sample_svp_rect; + + typedef struct { +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c +index 3f811f0..469ff32 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c +@@ -999,6 +999,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + td_float *y_min = TD_NULL; + td_float *x_max = TD_NULL; + td_float *y_max = TD_NULL; ++ td_float *score = TD_NULL; ++ td_float *class_id = TD_NULL; + td_u32 roi_offset = info->roi_offset; + td_u32 i; + +@@ -1019,6 +1021,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + y_min = x_min + stride / sizeof(td_float); + x_max = y_min + stride / sizeof(td_float); + y_max = x_max + stride / sizeof(td_float); ++ score = y_max + stride / sizeof(td_float); ++ class_id = score + stride / sizeof(td_float); + + for (i = 0; i < rect_info->num; i++) { + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)((td_float)x_min[roi_offset] / +@@ -1040,6 +1044,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; ++ rect_info->rect[i].score = (td_float)((td_float)score[roi_offset]); ++ rect_info->rect[i].class_id = (td_u16)((td_float)class_id[roi_offset]); + roi_offset++; + } + return TD_SUCCESS; +@@ -1319,6 +1325,9 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) + { + td_s32 ret; ++ td_u32 i; ++ td_float max_confidence = 0.0f; ++ td_u32 max_index = 0; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); +@@ -1341,6 +1350,19 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + ret = sample_svp_npu_get_roi(task, detection_info, proc_frame, show_frame, rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi failed!\n"); ++ if (rect_info->num > 0) { ++ for (i = 0; i < rect_info->num; i++) { ++ if (rect_info->rect[i].score > max_confidence) { ++ max_confidence = rect_info->rect[i].score; ++ max_index = i; ++ } ++ } ++ ++ if (rect_info->num > 1) { ++ rect_info->rect[0] = rect_info->rect[max_index]; ++ rect_info->num = 1; ++ } ++ } + + return TD_SUCCESS; + } +diff --git a/smp/a55_linux/mpp/sample/tde/Makefile b/smp/a55_linux/mpp/sample/tde/Makefile +index bf925b5..533ee73 100644 +--- a/smp/a55_linux/mpp/sample/tde/Makefile ++++ b/smp/a55_linux/mpp/sample/tde/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + SMP_SRCS := $(wildcard *.c) + TARGET := $(SMP_SRCS:%.c=%) + +-MPI_LIBS += $(REL_LIB)/libss_tde.so ++MPI_LIBS += -lss_tde + + TARGET_PATH := $(PWD) + +diff --git a/smp/a55_linux/mpp/sample/vio/sample_vio.c b/smp/a55_linux/mpp/sample/vio/sample_vio.c +index 9c29f05..627bb16 100644 +--- a/smp/a55_linux/mpp/sample/vio/sample_vio.c ++++ b/smp/a55_linux/mpp/sample/vio/sample_vio.c +@@ -63,7 +63,7 @@ static td_u16 g_lmf_coef[128] = { + static sample_vo_cfg g_vo_cfg = { + .vo_dev = SAMPLE_VO_DEV_UHD, + .vo_intf_type = OT_VO_INTF_HDMI, +- .intf_sync = OT_VO_OUT_1080P30, ++ .intf_sync = OT_VO_OUT_1080P60, + .bg_color = COLOR_RGB_BLACK, + .pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, + .disp_rect = {0, 0, 1920, 1080}, +diff --git a/smp/a55_linux/mpp/sample/vo/sample_vo.c b/smp/a55_linux/mpp/sample/vo/sample_vo.c +index b2db0cb..1baa0d5 100644 +--- a/smp/a55_linux/mpp/sample/vo/sample_vo.c ++++ b/smp/a55_linux/mpp/sample/vo/sample_vo.c +@@ -345,6 +345,184 @@ static mipi_tx_cmd_info g_cmd_info_1200x1920[CMD_COUNT_1200X1920] = { + {{0, 0, 0, 0x23, 0x0029, NULL}, USLEEP_60000}, + }; + ++#define CMD_DATA_COUNT_800X1280_ST 48 ++static unsigned char g_cmd_data_800x1280_st[CMD_DATA_COUNT_800X1280_ST][39] = { ++{0xE0,0xAB,0xBA}, ++{0xE1,0xBA,0xAB}, ++{0xB1,0x10,0x01,0x47,0xFF}, ++{0xB2,0x0c,0x0e,0x04,0x14,0x14,0x14}, ++{0xB3,0x56,0xD3,0x00}, ++{0xB4,0x22,0x30,0x04}, ++{0xB6,0xb0,0x00,0x00,0x10,0x00,0x10,0x00}, ++{0xB7,0x0E,0x00,0xFF,0x08,0x08,0xFF,0xFF,0x00}, ++{0xB8,0x05,0x12,0x29,0x49,0x48,0x00,0x00}, ++{0xB9,0x4d,0x42,0x38,0x31,0x33,0x27,0x2F,0x1B,0x36,0x35,0x35,0x53,0x41,0x49,0x3D,0x3d,0x33,0x29,0x26,0x4c,0x42,0x39,0x31,0x33,0x27,0x2F,0x1B,0x36,0x35,0x35,0x53,0x41,0x49,0x3D,0x3d,0x33,0x29,0x26}, ++{0xBA,0x00,0x00,0x00,0x44,0x24,0x00,0x00,0x00}, ++{0xBB,0x76,0x00,0x00}, ++{0xBC,0x00,0x00}, ++{0xBD,0xFF,0x00,0x00,0x00,0x00}, ++{0xC0,0x98,0x76,0x12,0x34,0x33,0x33,0x44,0x44,0x06,0x04,0x8A,0x04,0x0F,0x00,0x00,0x00}, ++{0xC1,0x53,0x94,0x02,0x85,0x06,0x04,0x8A,0x04,0x54,0x00}, ++{0xC2,0x37,0x09,0x08,0x89,0x08,0x10,0x22,0x21,0x44,0xBB,0x18,0x00}, ++{0xC3,0x9C,0x1D,0x1E,0x1F,0x10,0x12,0x0C,0x0E,0x05,0x24,0x24,0x24,0x24,0x24,0x24,0x07,0x24,0x24,0x24,0x24,0x24,0x24}, ++{0xC4,0x1C,0x1D,0x1E,0x1F,0x11,0x13,0x0D,0x0F,0x04,0x24,0x24,0x24,0x24,0x24,0x24,0x06,0x24,0x24,0x24,0x24,0x24,0x24}, ++{0xC5,0xE8,0x85,0x76}, ++{0xC6,0x20,0x20}, ++{0xC7,0x41,0x01,0x0D,0x11,0x09,0x15,0x19,0x4F,0x10,0xD7,0xCF,0x19,0x1B,0x1D,0x03,0x02,0x25,0x30,0x00,0x03,0xFF,0x00}, ++{0xC8,0x61,0x00,0x31,0x42,0x54,0x16}, ++{0xC9,0xA1,0x22,0xFF,0xCd,0x23}, ++{0xCA,0x4B,0x43}, ++{0xCC,0x2E,0x02,0x04,0x08}, ++{0xCD,0x0E,0x64,0x64,0x20,0x1E,0x6B,0x06,0x83}, ++{0xD0,0x27,0x10,0x80}, ++{0xD1,0x00,0x0D,0xFF,0x0F}, ++{0xD2,0xE3,0x2B,0x38,0x00}, ++{0xD4,0x00,0x01,0x00,0x0E,0x04,0x44,0x08,0x10,0x00,0x07,0x00}, ++{0xD6,0x00,0x00}, ++{0xD7,0x00,0x00,0x00,0x00}, ++{0xE4,0x08,0x55,0x03}, ++{0xE6,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++{0xE7,0x00,0x00,0x00}, ++{0xE8,0xD5,0xFF,0xFF,0xFF,0x00,0x00,0x00}, ++{0xF0,0x12,0x03,0x20,0x00,0xFF}, ++{0xF1,0xA6,0xC8,0xEA,0xE6,0xE4,0xCC,0xE4,0xBE,0xF0,0xB2,0xAA,0xC7,0xFF,0x66,0x98,0xE3,0x87,0xC8,0x99,0xC8,0x8C,0xBE,0x96,0x91,0x8F,0xFF}, ++{0xF4,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF5,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF6,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF7,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xFA,0x00,0x84,0x12,0x21,0x48,0x48,0x21,0x12,0x84,0x69,0x69,0x5A,0xA5,0x96,0x96,0xA5,0x5A,0xB7,0xDE,0xED,0x7B,0x7B,0xED,0xDE,0xB7}, ++{0xFB,0x00,0x12,0x0F,0xFF,0xFF,0xFF,0x00,0x38,0x40,0x08,0x70,0x0B,0x40,0x19,0x50,0x21,0xC0,0x27,0x60,0x2D,0x00,0x00,0x0F}, ++{0xE3,0x20,0x21}, ++}; ++#define UDELAY_50 50 ++#define CMD_COUNT_800X1280 56 ++static mipi_tx_cmd_info g_cmd_info_800x1280[CMD_COUNT_800X1280] = { ++ /* {devno work_mode lp_clk_en data_type cmd_size cmd}, usleep_value */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[0]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[1]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00B0, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[2]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x07, g_cmd_data_800x1280_st[3]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[4]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[5]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00B5, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[6]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[7]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[8]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x27, g_cmd_data_800x1280_st[9]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[10]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[11]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[12]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[13]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00BE, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x11, g_cmd_data_800x1280_st[14]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0b, g_cmd_data_800x1280_st[15]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0d, g_cmd_data_800x1280_st[16]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[17]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[18]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[19]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[20]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[21]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x07, g_cmd_data_800x1280_st[22]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[23]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[24]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[25]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[26]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[27]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[28]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[29]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0c, g_cmd_data_800x1280_st[30]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00D5, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[31]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[32]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[33]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[34]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[35]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[36]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0xFFE9, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[37]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[38]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x03F3, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[39]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[40]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[41]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[42]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[43]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[44]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1a, g_cmd_data_800x1280_st[45]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x18, g_cmd_data_800x1280_st[46]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[47]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x05, 0x0011, NULL}, 250000}, ++ {{0, 0, 1, 0x05, 0x0029, NULL}, 50000}, ++}; ++/* VO: USER 800x1280_60, TX: USER 800x1280 */ ++static const sample_vo_mipi_tx_cfg g_vo_tx_cfg_800x1280_user = { ++ .vo_config = { ++ .vo_dev = SAMPLE_VO_DEV_UHD, ++ .vo_intf_type = OT_VO_INTF_MIPI, ++ .intf_sync = OT_VO_OUT_USER, ++ .bg_color = COLOR_RGB_BLUE, ++ .pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, ++ .disp_rect = {0, 0, 800, 1280}, ++ .image_size = {800, 1280}, ++ .vo_part_mode = OT_VO_PARTITION_MODE_SINGLE, ++ .dis_buf_len = 3, /* 3: def buf len for single */ ++ .dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8, ++ .vo_mode = VO_MODE_1MUX, ++ .compress_mode = OT_COMPRESS_MODE_NONE, ++ ++ .sync_info = {0, 1, 1, 1280, 21, 16, 800, 68, 48, 1, 1, 1, 1, 20, 6, 0, 0, 0}, ++ //.sync_info = {0, 1, 1, 1280, 21, 16, 800, 68, 48, 1, 1, 1, 1, 20, 6, 0, 0, 0}, ++ .user_sync = { ++ .user_sync_attr = { ++ .clk_src = OT_VO_CLK_SRC_PLL, ++ .vo_pll = { /* if hdmi, set it by pixel clk and div mode */ ++ .fb_div = 34, /* 72 fb div */ ++ .frac = 0, ++ .ref_div = 1, /* 1 ref div */ ++ .post_div1 = 4, /* 6 post div1 */ ++ .post_div2 = 3, /* 2 post div2 */ ++ }, ++ }, ++ .pre_div = 1, /* if hdmi, set it by pixel clk */ ++ .dev_div = 1, /* if rgb, set it by serial mode */ ++ .clk_reverse_en = TD_FALSE, ++ }, ++ .dev_frame_rate = SAMPLE_VO_DEV_FRAME_RATE, ++ }, ++ .tx_config = { ++ /* for combo dev config */ ++ .intf_sync = OT_MIPI_TX_OUT_USER, ++ ++ /* for screen cmd */ ++ .cmd_count = CMD_COUNT_800X1280, ++ .cmd_info = g_cmd_info_800x1280, ++ ++ /* for user sync */ ++ .combo_dev_cfg = { ++ .devno = 0, ++ .lane_id = {0, 1, 2, 3}, ++ .out_mode = OUT_MODE_DSI_VIDEO, ++ .out_format = OUT_FORMAT_RGB_24BIT, ++ .video_mode = BURST_MODE, ++ .sync_info = { ++ .hsa_pixels = 20, /* 20 pixel */ ++ .hbp_pixels = 48, /* 48 pixel */ ++ .hact_pixels = 800, /* 800 pixel */ ++ .hfp_pixels = 48, /* 48 pixel */ ++ .vsa_lines = 6, /* 6 line */ ++ .vbp_lines = 15, /* 15 line */ ++ .vact_lines = 1280, /* 1280 line */ ++ .vfp_lines = 16, /* 16 line */ ++ }, ++ .phy_data_rate = 435, /* 435 Mbps */ ++ .pixel_clk = 68000, /* 68000 KHz */ ++ }, ++ }, ++}; ++ + /* VO: USER 1200x1920_60, TX: USER 1200x1920 */ + static const sample_vo_mipi_tx_cfg g_vo_tx_cfg_1200x1920_user = { + .vo_config = { +@@ -630,17 +808,22 @@ static td_s32 sample_vo_mipi_tx_1200x1920_user(td_void) + return sample_vo_mipi_tx(&g_vo_tx_cfg_1200x1920_user); + } + ++static td_s32 sample_vo_mipi_tx_800x1280_user(td_void) ++{ ++ return sample_vo_mipi_tx(&g_vo_tx_cfg_800x1280_user); ++} ++ + static void sample_vo_usage(const char *name) + { + printf("usage : %s \n", name); + printf("index:\n"); +- printf("\t0: vo dhd0 mipi_tx USER 1200x1920@60 output.\n"); ++ printf("\t0: vo dhd0 mipi_tx USER 800x1280@60 output.\n"); + } + + static td_s32 sample_vo_execute_case(td_s32 index) + { + if (index == 0) { +- return sample_vo_mipi_tx_1200x1920_user(); ++ return sample_vo_mipi_tx_800x1280_user(); + } + + sample_print("the index %d is invalid!\n", index); diff --git a/vendor/zsks/patch/clang/0001-support-USB-Camera-and-zsks-demo.patch b/vendor/zsks/patch/clang/0001-support-USB-Camera-and-zsks-demo.patch deleted file mode 100755 index 7de9cffd36a82095910acd011f0ec119d2c6d95a..0000000000000000000000000000000000000000 --- a/vendor/zsks/patch/clang/0001-support-USB-Camera-and-zsks-demo.patch +++ /dev/null @@ -1,558 +0,0 @@ -From 013c6daae38a3ee9dd2ed98479b2db209ec589e0 Mon Sep 17 00:00:00 2001 -From: wgm2022 <1480559020@qq.com> -Date: Wed, 31 Dec 2025 10:58:23 +0800 -Subject: [PATCH] support USB Camera and zsks demo - ---- - smp/a55_linux/mpp/sample/common/Makefile | 2 + - smp/a55_linux/mpp/sample/common/sample_comm.h | 7 + - .../mpp/sample/common/sample_comm_isp.c | 21 ++ - .../mpp/sample/common/sample_comm_vdec.c | 229 ++++++++++++++++++ - .../mpp/sample/common/sample_comm_vi.c | 28 ++- - .../mpp/sample/svp/common/sample_common_svp.c | 4 +- - .../mpp/sample/svp/common/sample_common_svp.h | 2 + - .../svp/common/sample_common_svp_npu_model.c | 22 ++ - 8 files changed, 311 insertions(+), 4 deletions(-) - -diff --git a/smp/a55_linux/mpp/sample/common/Makefile b/smp/a55_linux/mpp/sample/common/Makefile -index 502ec11..3c5db63 100644 ---- a/smp/a55_linux/mpp/sample/common/Makefile -+++ b/smp/a55_linux/mpp/sample/common/Makefile -@@ -1,6 +1,8 @@ - param_file=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))/../Makefile.param - include $(param_file) - -+CFLAGS += -fPIC -+ - .PHONY : clean all - all:$(COMM_OBJ) - -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm.h b/smp/a55_linux/mpp/sample/common/sample_comm.h -index cc50e0c..c8a96e5 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm.h -+++ b/smp/a55_linux/mpp/sample/common/sample_comm.h -@@ -235,6 +235,7 @@ typedef enum { - OV_OS08A20_MIPI_8M_30FPS_12BIT, - OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1, - OV_OS04A10_MIPI_4M_30FPS_12BIT, -+ OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1, - SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT, - SC450AI_MIPI_4M_30FPS_10BIT, - SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1, -@@ -546,6 +547,12 @@ typedef struct { - td_u64 last_time; - td_u64 time_gap; - td_u64 fps; -+# ifdef USE_USB_CAMERA -+ td_char *v4l2_device; -+ td_u32 width; -+ td_u32 height; -+ td_u32 pixel_format; -+# endif - } vdec_thread_param; - - typedef struct { -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -index 982efa3..0d86d9a 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -@@ -53,6 +53,7 @@ static ot_isp_sns_type g_sns_type[OT_VI_MAX_PIPE_NUM] = {(ot_isp_sns_type)SNS_TY - static pthread_t g_isp_pid[OT_VI_MAX_DEV_NUM] = {0}; - - extern ot_isp_sns_obj g_sns_hy_s0603_obj; -+extern ot_isp_sns_obj g_sns_os04a10_obj; - - /* IspPub attr */ - static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps = { -@@ -130,6 +131,21 @@ static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps = { - }, - }; - -+static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1 = { -+ {0, 0, WIDTH_2688, HEIGHT_1520}, -+ {WIDTH_2688, HEIGHT_1520}, -+ 30, -+ OT_ISP_BAYER_RGGB, -+ OT_WDR_MODE_2To1_LINE, -+ 0, -+ 0, -+ 0, -+ { -+ 0, -+ {0, 0, 2688, 1520}, -+ }, -+}; -+ - static ot_isp_pub_attr g_isp_pub_attr_imx347_slave_mipi_4m_30fps = { - {0, 20, WIDTH_2592, HEIGHT_1520}, - {WIDTH_2592, HEIGHT_1520}, -@@ -228,6 +244,10 @@ td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_ - (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), - &g_isp_pub_attr_os04a10_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); - break; -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), -+ &g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); -+ break; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), - &g_isp_pub_attr_imx347_slave_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); -@@ -267,6 +287,7 @@ ot_isp_sns_obj *sample_comm_isp_get_sns_obj(sample_sns_type sns_type) - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - return &g_sns_os08a20_obj; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return &g_sns_os04a10_obj; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - return &g_sns_imx347_slave_obj; -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -index a0c9ad9..517b6d3 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -@@ -32,6 +32,17 @@ - #include - #include "sample_comm.h" - -+#ifdef USE_USB_CAMERA -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#endif -+ - #define SEND_STREAM_CNT 5 - #define VDEC_SECOND 1000000 - #define SAMPLE_VDEC_LOW_DELAY_LINE_CNT 16 -@@ -633,6 +644,223 @@ td_s32 sample_comm_vdec_check_send_stream_param(vdec_thread_param *thread_param, - return TD_SUCCESS; - } - -+ -+#ifdef USE_USB_CAMERA -+ -+td_void *sample_comm_vdec_send_stream(td_void *args) -+{ -+ printf("vdec send stream thread start\n"); -+ -+ vdec_thread_param *thread_param = (vdec_thread_param *)args; -+ ot_vdec_stream stream; -+ printf("sample_comm_vdec_send_stream v4l2 \r\n"); -+ -+ td_s32 v4l2_fd = -1; -+ struct v4l2_capability cap; -+ struct v4l2_format fmt; -+ struct v4l2_requestbuffers req; -+ struct v4l2_buffer v4l2_buf; -+ enum v4l2_buf_type buf_type; -+ fd_set fds; -+ struct timeval tv; -+ td_u8 *v4l2_buffers[4] = {NULL}; -+ td_u32 buffer_count = 0; -+ td_u32 max_buffer_length = 0; -+ -+ prctl(PR_SET_NAME, "v4l2_to_vdec", 0, 0, 0); -+ -+ if (thread_param == NULL) { -+ sample_print("̲߳Ϊ!"); -+ return (td_void *)TD_FAILURE; -+ } -+ -+ sample_print("v4l2ͷɼ: %s", thread_param->v4l2_device); -+ v4l2_fd = open(thread_param->v4l2_device, O_RDWR | O_NONBLOCK, 0); -+ if (v4l2_fd < 0) { -+ sample_print("޷ͷ %s: %s", -+ thread_param->v4l2_device, strerror(errno)); -+ return (td_void *)(TD_FAILURE); -+ } -+ -+ if (ioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) { -+ sample_print("VIDIOC_QUERYCAP: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { -+ sample_print("豸֧ʽ"); -+ goto v4l2_cleanup; -+ } -+ -+ memset(&fmt, 0, sizeof(fmt)); -+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ fmt.fmt.pix.width = thread_param->width; -+ fmt.fmt.pix.height = thread_param->height; -+ fmt.fmt.pix.pixelformat = thread_param->pixel_format; -+ fmt.fmt.pix.field = V4L2_FIELD_ANY; -+ -+ if (ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt) < 0) { -+ sample_print("VIDIOC_S_FMT: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ struct v4l2_streamparm parm; -+ memset(&parm, 0, sizeof(parm)); -+ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ parm.parm.capture.timeperframe.numerator = 1; -+ parm.parm.capture.timeperframe.denominator = thread_param->fps; -+ if (ioctl(v4l2_fd, VIDIOC_S_PARM, &parm) < 0) { -+ sample_print("֡ʧܣʹĬֵ: %s", strerror(errno)); -+ } -+ -+ memset(&req, 0, sizeof(req)); -+ req.count = 4; -+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ req.memory = V4L2_MEMORY_MMAP; -+ -+ if (ioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { -+ sample_print("VIDIOC_REQBUFS: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ buffer_count = req.count; -+ max_buffer_length = 0; -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ v4l2_buf.index = i; -+ -+ if (ioctl(v4l2_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QUERYBUF: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ if (v4l2_buf.length > max_buffer_length) { -+ max_buffer_length = v4l2_buf.length; -+ } -+ -+ v4l2_buffers[i] = mmap(NULL, v4l2_buf.length, -+ PROT_READ | PROT_WRITE, -+ MAP_SHARED, -+ v4l2_fd, -+ v4l2_buf.m.offset); -+ -+ if (v4l2_buffers[i] == MAP_FAILED) { -+ sample_print("mmapʧ: %s", strerror(errno)); -+ v4l2_buffers[i] = NULL; -+ goto v4l2_cleanup; -+ } -+ } -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ v4l2_buf.index = i; -+ -+ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QBUF: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ } -+ -+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ if (ioctl(v4l2_fd, VIDIOC_STREAMON, &buf_type) < 0) { -+ sample_print("VIDIOC_STREAMON: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ sample_print("v4l2ͷ: %s, %dx%d@%llufps, ʽ: %c%c%c%c", -+ thread_param->v4l2_device, -+ thread_param->width, -+ thread_param->height, -+ thread_param->fps, -+ thread_param->pixel_format & 0xFF, -+ (thread_param->pixel_format >> 8) & 0xFF, -+ (thread_param->pixel_format >> 16) & 0xFF, -+ (thread_param->pixel_format >> 24) & 0xFF); -+ -+ while (thread_param->e_thread_ctrl == THREAD_CTRL_START) { -+ FD_ZERO(&fds); -+ FD_SET(v4l2_fd, &fds); -+ -+ tv.tv_sec = 2; -+ tv.tv_usec = 0; -+ -+ td_s32 r = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); -+ if (r == -1) { -+ if (errno == EINTR) continue; -+ sample_print("select: %s", strerror(errno)); -+ break; -+ } -+ -+ if (r == 0) { -+ sample_print("selectʱ"); -+ continue; -+ } -+ -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ -+ if (ioctl(v4l2_fd, VIDIOC_DQBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_DQBUF: %s", strerror(errno)); -+ continue; -+ } -+ -+ if (v4l2_buf.bytesused == 0) { -+ sample_print("յ֡"); -+ goto requeue_buffer; -+ } -+ -+ memset(&stream, 0, sizeof(ot_vdec_stream)); -+ stream.addr = v4l2_buffers[v4l2_buf.index]; -+ stream.len = v4l2_buf.bytesused; -+ stream.end_of_stream = TD_FALSE; -+ -+ struct timeval now; -+ gettimeofday(&now, NULL); -+ stream.pts = now.tv_sec * 1000000 + now.tv_usec; -+ -+ td_s32 s32Ret = ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, 30); -+ if (s32Ret != TD_SUCCESS) { -+ sample_print("͵VDECʧ, ret=%#x", s32Ret); -+ } -+ -+requeue_buffer: -+ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QBUF: %s", strerror(errno)); -+ break; -+ } -+ } -+ -+ memset(&stream, 0, sizeof(ot_vdec_stream)); -+ stream.end_of_stream = TD_TRUE; -+ ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, -1); -+ -+ sample_print("v4l2ɼ߳˳"); -+ -+v4l2_cleanup: -+ if (v4l2_fd >= 0) { -+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ ioctl(v4l2_fd, VIDIOC_STREAMOFF, &buf_type); -+ } -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ if (v4l2_buffers[i]) { -+ munmap(v4l2_buffers[i], max_buffer_length); -+ } -+ } -+ -+ if (v4l2_fd >= 0) { -+ close(v4l2_fd); -+ } -+ -+ return (td_void *)TD_SUCCESS; -+} -+#else - td_void *sample_comm_vdec_send_stream(td_void *args) - { - vdec_thread_param *thread_param = (vdec_thread_param *)args; -@@ -691,6 +919,7 @@ end1: - path = TD_NULL; - return (td_void *)TD_SUCCESS; - } -+#endif - - td_void sample_comm_vdec_cmd_not_circle_send(td_u32 chn_num, vdec_thread_param *vdec_send, - pthread_t *vdec_thread, td_u32 send_arr_len, td_u32 thread_arr_len) -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -index 5be7e63..8e999f6 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -@@ -172,6 +172,18 @@ static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_att - } - }; - -+static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr = { -+ .devno = 0, -+ .input_mode = INPUT_MODE_MIPI, -+ .data_rate = MIPI_DATA_RATE_X1, -+ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, -+ .mipi_attr = { -+ DATA_TYPE_RAW_10BIT, -+ OT_MIPI_WDR_MODE_VC, -+ {0, 1, 2, 3, -1, -1, -1, -1} -+ } -+}; -+ - static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr = { - .devno = 0, - .input_mode = INPUT_MODE_MIPI, -@@ -364,10 +376,16 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); - break; -- case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ //ob_height = OB_HEIGHT_END; - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); - break; -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ ob_height = OB_HEIGHT_END; -+ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -+ &g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); -+ break; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - ob_height = IMX347_OB_HEIGHT_END; - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -@@ -388,7 +406,7 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ - - default: - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -- &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); -+ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); - } - combo_attr->img_rect.height = combo_attr->img_rect.height + ob_height; - } -@@ -400,6 +418,7 @@ static td_void sample_comm_vi_get_mipi_ext_data_attr(sample_sns_type sns_type, e - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT: - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -@@ -445,6 +464,7 @@ static td_void sample_comm_vi_get_mipi_attr_by_dev_id(sample_sns_type sns_type, - } - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ //ob_height = OB_HEIGHT_END; - if (vi_dev == 0) { - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); -@@ -599,6 +619,7 @@ td_void sample_comm_vi_get_size_by_sns_type(sample_sns_type sns_type, ot_size *s - size->height = HEIGHT_2160; - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_2L_MIPI_4M_30FPS_10BIT: -@@ -635,6 +656,7 @@ td_u32 sample_comm_vi_get_obheight_by_sns_type(sample_sns_type sns_type) - ob_height = IMX347_OB_HEIGHT_END; - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_2L_MIPI_4M_30FPS_10BIT: -@@ -663,6 +685,7 @@ static td_u32 sample_comm_vi_get_pipe_num_by_sns_type(sample_sns_type sns_type) - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return 2; /* 2 pipe */ - - default: -@@ -685,6 +708,7 @@ static ot_wdr_mode sample_comm_vi_get_wdr_mode_by_sns_type(sample_sns_type sns_t - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return OT_WDR_MODE_2To1_LINE; - - default: -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -index 6d6e27b..b2eb9d8 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -@@ -444,7 +444,7 @@ static td_void sample_common_svp_stop_vpss(td_s32 vpss_grp_cnt, td_u32 vpss_chn_ - } - } - --static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) -+td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) - { - ot_rect def_disp_rect = {0, 0, 1920, 1080}; - ot_size def_img_size = {1920, 1080}; -@@ -457,7 +457,7 @@ static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) - vo_cfg->vo_dev = SAMPLE_VO_DEV_UHD; - - vo_cfg->vo_intf_type = OT_VO_INTF_HDMI; -- vo_cfg->intf_sync = OT_VO_OUT_1080P30; -+ vo_cfg->intf_sync = OT_VO_OUT_1080P60; - vo_cfg->bg_color = COLOR_RGB_BLACK; - vo_cfg->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - vo_cfg->disp_rect = def_disp_rect; -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -index 626a2d6..dd86d96 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -@@ -60,6 +60,8 @@ typedef enum { - - typedef struct { - ot_point point[OT_POINT_NUM]; -+ td_float score; -+ td_u16 class_id; - } ot_sample_svp_rect; - - typedef struct { -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -index 3f811f0..469ff32 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -@@ -999,6 +999,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - td_float *y_min = TD_NULL; - td_float *x_max = TD_NULL; - td_float *y_max = TD_NULL; -+ td_float *score = TD_NULL; -+ td_float *class_id = TD_NULL; - td_u32 roi_offset = info->roi_offset; - td_u32 i; - -@@ -1019,6 +1021,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - y_min = x_min + stride / sizeof(td_float); - x_max = y_min + stride / sizeof(td_float); - y_max = x_max + stride / sizeof(td_float); -+ score = y_max + stride / sizeof(td_float); -+ class_id = score + stride / sizeof(td_float); - - for (i = 0; i < rect_info->num; i++) { - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)((td_float)x_min[roi_offset] / -@@ -1040,6 +1044,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; -+ rect_info->rect[i].score = (td_float)((td_float)score[roi_offset]); -+ rect_info->rect[i].class_id = (td_u16)((td_float)class_id[roi_offset]); - roi_offset++; - } - return TD_SUCCESS; -@@ -1319,6 +1325,9 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, - const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) - { - td_s32 ret; -+ td_u32 i; -+ td_float max_confidence = 0.0f; -+ td_u32 max_index = 0; - - if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { - sample_svp_trace_err("check task cfg failed!\n"); -@@ -1341,6 +1350,19 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, - ret = sample_svp_npu_get_roi(task, detection_info, proc_frame, show_frame, rect_info); - sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, - "get roi failed!\n"); -+ if (rect_info->num > 0) { -+ for (i = 0; i < rect_info->num; i++) { -+ if (rect_info->rect[i].score > max_confidence) { -+ max_confidence = rect_info->rect[i].score; -+ max_index = i; -+ } -+ } -+ -+ if (rect_info->num > 1) { -+ rect_info->rect[0] = rect_info->rect[max_index]; -+ rect_info->num = 1; -+ } -+ } - - return TD_SUCCESS; - } --- -2.34.1 - diff --git a/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-mipi-camera.patch b/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-mipi-camera.patch new file mode 100755 index 0000000000000000000000000000000000000000..c7681102383d8bb0e76e4919a37b56b173c506eb --- /dev/null +++ b/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-mipi-camera.patch @@ -0,0 +1,1701 @@ +From 3eaca2c56010ba5d7964db79c06d7042b5204488 Mon Sep 17 00:00:00 2001 +From: wgm <1480559020@qq.com> +Date: Tue, 19 May 2026 15:52:23 +0800 +Subject: [PATCH] support-USB-Camera-and-mipi-camera + +diff --git a/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h b/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h +index 03f7ccf..3b72e7d 100644 +--- a/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h ++++ b/smp/a55_linux/mpp/out/include/ot_sns_ctrl.h +@@ -78,6 +78,11 @@ typedef struct { + } ot_isp_sns_obj; + + extern ot_isp_sns_obj g_sns_hy_s0603_obj; ++extern ot_isp_sns_obj g_sns_os08a20_obj; ++extern ot_isp_sns_obj g_sns_imx347_slave_obj; ++extern ot_isp_sns_obj g_sns_os04a10_obj; ++extern ot_isp_sns_obj g_sns_sc450ai_obj; ++extern ot_isp_sns_obj g_sns_sc450ai_2l_obj; + + #define sensor_check_pointer_return(ptr) \ + do { \ +diff --git a/smp/a55_linux/mpp/sample/Makefile.param b/smp/a55_linux/mpp/sample/Makefile.param +index 88aead8..f8a51a1 100644 +--- a/smp/a55_linux/mpp/sample/Makefile.param ++++ b/smp/a55_linux/mpp/sample/Makefile.param +@@ -7,44 +7,56 @@ endif + ################# select sensor type for your sample ############################### + #### HY_S0603_MIPI_8M_30FPS_12BIT ################# + #### HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1 ################# +- ++#### OV_OS08A20_MIPI_8M_30FPS_12BIT ################# ++#### OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1 ################# ++#### SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT ################# ++#### OV_OS04A10_MIPI_4M_30FPS_12BIT ################# ++#### SC450AI_MIPI_4M_30FPS_10BIT ################# ++#### SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1 ################# ++#### SC450AI_2L_MIPI_4M_30FPS_10BIT ################# ++#### SC450AI_2L_MIPI_2M_30FPS_10BIT ################# ++#### SC450AI_2L_MIPI_1344x760_30FPS_10BIT ################# + ## change sensor type here. default: hy_s0603 + +-SENSOR0_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR1_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR2_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT +-SENSOR3_TYPE ?= HY_S0603_MIPI_8M_30FPS_12BIT ++SENSOR0_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR1_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR2_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT ++SENSOR3_TYPE ?= OV_OS04A10_MIPI_4M_30FPS_12BIT + +-MPI_LIBS := $(REL_LIB)/libss_mpi.so ++MPI_LIBS := -lss_mpi + + ifeq ($(CONFIG_OT_ISP_SUPPORT), y) +-MPI_LIBS += $(REL_LIB)/libss_ae.so +-MPI_LIBS += $(REL_LIB)/libss_isp.so +-MPI_LIBS += $(REL_LIB)/libot_isp.so +-MPI_LIBS += $(REL_LIB)/libss_awb.so +-MPI_LIBS += $(REL_LIB)/libss_dehaze.so +-MPI_LIBS += $(REL_LIB)/libss_extend_stats.so +-MPI_LIBS += $(REL_LIB)/libss_drc.so +-MPI_LIBS += $(REL_LIB)/libss_ldci.so +-MPI_LIBS += $(REL_LIB)/libss_crb.so +-MPI_LIBS += $(REL_LIB)/libss_bnr.so +-MPI_LIBS += $(REL_LIB)/libss_calcflicker.so +-MPI_LIBS += $(REL_LIB)/libss_ir_auto.so +-MPI_LIBS += $(REL_LIB)/libss_acs.so +-MPI_LIBS += $(REL_LIB)/libsns_hy_s0603.so +- ++MPI_LIBS += -lss_ae ++MPI_LIBS += -lss_isp ++MPI_LIBS += -lot_isp ++MPI_LIBS += -lss_awb ++MPI_LIBS += -lss_dehaze ++MPI_LIBS += -lss_extend_stats ++MPI_LIBS += -lss_drc ++MPI_LIBS += -lss_ldci ++MPI_LIBS += -lss_crb ++MPI_LIBS += -lss_bnr ++MPI_LIBS += -lss_calcflicker ++MPI_LIBS += -lss_ir_auto ++MPI_LIBS += -lss_acs ++MPI_LIBS += -lsns_hy_s0603 ++MPI_LIBS += -lsns_os08a20 ++MPI_LIBS += -lsns_imx347_slave ++MPI_LIBS += -lsns_os04a10 ++MPI_LIBS += -lsns_sc450ai ++MPI_LIBS += -lsns_sc450ai_2l + endif + + + ifeq ($(CONFIG_OT_AUDIO_SUPPORT), y) +-AUDIO_LIBA := $(REL_LIB)/libss_voice_engine.so +-AUDIO_LIBA += $(REL_LIB)/libss_upvqe.so +-AUDIO_LIBA += $(REL_LIB)/libss_dnvqe.so +-AUDIO_LIBA += $(REL_LIB)/libaac_comm.so +-AUDIO_LIBA += $(REL_LIB)/libaac_enc.so +-AUDIO_LIBA += $(REL_LIB)/libaac_dec.so +-AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.so +-AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.so ++AUDIO_LIBA := -lss_voice_engine ++AUDIO_LIBA += -lss_upvqe ++AUDIO_LIBA += -lss_dnvqe ++AUDIO_LIBA += -laac_comm ++AUDIO_LIBA += -laac_enc ++AUDIO_LIBA += -laac_dec ++AUDIO_LIBA += -laac_sbr_enc ++AUDIO_LIBA += -laac_sbr_dec + endif + + COMMON_DIR ?= $(PWD)/../common +@@ -103,22 +115,22 @@ AUDIO_MODULE_LIB_TYPE ?= AUDIO_LIB_TYPE_STATIC + ifeq ($(AUDIO_MODULE_LIB_TYPE), AUDIO_LIB_TYPE_STATIC) + ##### VQE ##### + CFLAGS += -DOT_VQE_USE_STATIC_MODULE_REGISTER +- AUDIO_LIBA += $(REL_LIB)/libvqe_res.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_record.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_hpf.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_anr.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_aec.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_agc.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_eq.so +- AUDIO_LIBA += $(REL_LIB)/libvqe_talkv2.so ++ AUDIO_LIBA += -lvqe_res ++ AUDIO_LIBA += -lvqe_record ++ AUDIO_LIBA += -lvqe_hpf ++ AUDIO_LIBA += -lvqe_anr ++ AUDIO_LIBA += -lvqe_aec ++ AUDIO_LIBA += -lvqe_agc ++ AUDIO_LIBA += -lvqe_eq ++ AUDIO_LIBA += -lvqe_talkv2 + ##### AAC ##### + CFLAGS += -DOT_AAC_USE_STATIC_MODULE_REGISTER +- AUDIO_LIBA += $(REL_LIB)/libaac_dec.so +- AUDIO_LIBA += $(REL_LIB)/libaac_enc.so +- AUDIO_LIBA += $(REL_LIB)/libaac_comm.so ++ AUDIO_LIBA += -laac_dec ++ AUDIO_LIBA += -laac_enc ++ AUDIO_LIBA += -laac_comm + CFLAGS += -DOT_AAC_HAVE_SBR_LIB +- AUDIO_LIBA += $(REL_LIB)/libaac_sbr_dec.so +- AUDIO_LIBA += $(REL_LIB)/libaac_sbr_enc.so ++ AUDIO_LIBA += -laac_sbr_dec ++ AUDIO_LIBA += -laac_sbr_enc + endif + endif + +@@ -127,7 +139,7 @@ GYRO_DIS ?= n + + ifeq ($(GYRO_DIS), y) + CFLAGS += -DOT_GYRODIS_SUPPORT +- MPI_LIBS += $(REL_LIB)/libss_motionfusion.so ++ MPI_LIBS += -lss_motionfusion + endif + + ######################################################################### +@@ -167,9 +179,8 @@ MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/ipcmsg/include + MEDIA_MSG_INC += -I$(SDK_PATH)/ot_syslink/datafifo/include + + ifeq ($(CONFIG_DRIVER_SPACE_TYPE),user_space) +-MPI_LIBS += $(REL_LIB)/svp_npu/libsvp_acl.so +-MPI_LIBS += -L$(REL_LIB)/svp_npu -lprotobuf-c +-SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/extdrv ++MPI_LIBS += -lsvp_acl -lprotobuf-c ++SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/svp_npu + SDK_LIB := $(SDK_LIB_PATH) + SDK_LIB += -l$(KO_PREFIX)_osal + SDK_LIB += -l$(KO_PREFIX)_base +@@ -192,16 +203,16 @@ SDK_LIB += -l$(KO_PREFIX)_vi + SDK_LIB += -l$(KO_PREFIX)_mpi_isp + SDK_LIB += -l$(KO_PREFIX)_rc + SDK_LIB += -l$(KO_PREFIX)_jpegd +-SDK_LIB += $(REL_LIB)/libss_hdmi.so ++SDK_LIB += -lss_hdmi + SDK_LIB += -l$(KO_PREFIX)_vfmw + SDK_LIB += -l$(KO_PREFIX)_gdc + SDK_LIB += -l$(KO_PREFIX)_dis + SDK_LIB += -l$(KO_PREFIX)_irq +-SDK_LIB += $(REL_LIB)/libss_dpu_match.so +-SDK_LIB += $(REL_LIB)/libss_dpu_rect.so +-SDK_LIB += $(REL_LIB)/libss_mau.so +-SDK_LIB += $(REL_LIB)/libss_ive.so +-SDK_LIB += $(REL_LIB)/libss_pqp.so ++SDK_LIB += -lss_dpu_match ++SDK_LIB += -lss_dpu_rect ++SDK_LIB += -lss_mau ++SDK_LIB += -lss_ive ++SDK_LIB += -lss_pqp + #SDK_LIB += -l$(KO_PREFIX)_avs + # SDK_LIB += -l$(KO_PREFIX)_mcf + # SDK_LIB += -l$(KO_PREFIX)_mcf_vi +diff --git a/smp/a55_linux/mpp/sample/common/Makefile b/smp/a55_linux/mpp/sample/common/Makefile +index 502ec11..3c5db63 100644 +--- a/smp/a55_linux/mpp/sample/common/Makefile ++++ b/smp/a55_linux/mpp/sample/common/Makefile +@@ -1,6 +1,8 @@ + param_file=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))/../Makefile.param + include $(param_file) + ++CFLAGS += -fPIC ++ + .PHONY : clean all + all:$(COMM_OBJ) + +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm.h b/smp/a55_linux/mpp/sample/common/sample_comm.h +index 10c8cbd..c8a96e5 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm.h ++++ b/smp/a55_linux/mpp/sample/common/sample_comm.h +@@ -232,6 +232,15 @@ typedef enum { + typedef enum { + HY_S0603_MIPI_8M_30FPS_12BIT, + HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1, ++ OV_OS08A20_MIPI_8M_30FPS_12BIT, ++ OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1, ++ OV_OS04A10_MIPI_4M_30FPS_12BIT, ++ OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1, ++ SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT, ++ SC450AI_MIPI_4M_30FPS_10BIT, ++ SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1, ++ SC450AI_2L_MIPI_4M_30FPS_10BIT, ++ SC450AI_2L_MIPI_2M_30FPS_10BIT, + SNS_TYPE_BUTT, + } sample_sns_type; + +@@ -538,6 +547,12 @@ typedef struct { + td_u64 last_time; + td_u64 time_gap; + td_u64 fps; ++# ifdef USE_USB_CAMERA ++ td_char *v4l2_device; ++ td_u32 width; ++ td_u32 height; ++ td_u32 pixel_format; ++# endif + } vdec_thread_param; + + typedef struct { +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c +index 52d2aaf..aef5725 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c +@@ -52,8 +52,6 @@ + static ot_isp_sns_type g_sns_type[OT_VI_MAX_PIPE_NUM] = {(ot_isp_sns_type)SNS_TYPE_BUTT}; + static pthread_t g_isp_pid[OT_VI_MAX_DEV_NUM] = {0}; + +-extern ot_isp_sns_obj g_sns_hy_s0603_obj; +- + /* IspPub attr */ + static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps = { + {0, 32, 3840, 2160}, +@@ -85,6 +83,141 @@ static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps_wdr2to1 = { + }, + }; + ++static ot_isp_pub_attr g_isp_pub_attr_os08a20_mipi_8m_30fps = { ++ {0, 24, 3840, 2160}, ++ {3840, 2160}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 3840, 2180}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os08a20_mipi_8m_30fps_wdr2to1 = { ++ {0, 24, 3840, 2160}, ++ {3840, 2160}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 3840, 2180}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1 = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_imx347_slave_mipi_4m_30fps = { ++ {0, 20, WIDTH_2592, HEIGHT_1520}, ++ {WIDTH_2592, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_RGGB, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2592, 1540}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_mipi_4m_30fps_wdr2to1 = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_2To1_LINE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_2l_mipi_4m_30fps = { ++ {0, 0, WIDTH_2688, HEIGHT_1520}, ++ {WIDTH_2688, HEIGHT_1520}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 2688, 1520}, ++ }, ++}; ++ ++static ot_isp_pub_attr g_isp_pub_attr_sc450ai_2l_mipi_2m_30fps = { ++ {0, 0, FHD_WIDTH, FHD_HEIGHT}, ++ {FHD_WIDTH, FHD_HEIGHT}, ++ 30, ++ OT_ISP_BAYER_BGGR, ++ OT_WDR_MODE_NONE, ++ 0, ++ 0, ++ 0, ++ { ++ 0, ++ {0, 0, 1920, 1080}, ++ }, ++}; ++ + td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_attr *pub_attr) + { + switch (sns_type) { +@@ -96,6 +229,42 @@ td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_ + (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), + &g_isp_pub_attr_hy_s0603_mipi_8m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os08a20_mipi_8m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os08a20_mipi_8m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os04a10_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_imx347_slave_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_2l_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), ++ &g_isp_pub_attr_sc450ai_2l_mipi_2m_30fps, sizeof(ot_isp_pub_attr)); ++ break; + default: + (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), + &g_isp_pub_attr_hy_s0603_mipi_8m_30fps, sizeof(ot_isp_pub_attr)); +@@ -111,6 +280,20 @@ ot_isp_sns_obj *sample_comm_isp_get_sns_obj(sample_sns_type sns_type) + case HY_S0603_MIPI_8M_30FPS_12BIT: + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + return &g_sns_hy_s0603_obj; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ return &g_sns_os08a20_obj; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ return &g_sns_os04a10_obj; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ return &g_sns_imx347_slave_obj; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ return &g_sns_sc450ai_obj; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ return &g_sns_sc450ai_2l_obj; + default: + return TD_NULL; + } +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c +index a0c9ad9..517b6d3 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c +@@ -32,6 +32,17 @@ + #include + #include "sample_comm.h" + ++#ifdef USE_USB_CAMERA ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++ + #define SEND_STREAM_CNT 5 + #define VDEC_SECOND 1000000 + #define SAMPLE_VDEC_LOW_DELAY_LINE_CNT 16 +@@ -633,6 +644,223 @@ td_s32 sample_comm_vdec_check_send_stream_param(vdec_thread_param *thread_param, + return TD_SUCCESS; + } + ++ ++#ifdef USE_USB_CAMERA ++ ++td_void *sample_comm_vdec_send_stream(td_void *args) ++{ ++ printf("vdec send stream thread start\n"); ++ ++ vdec_thread_param *thread_param = (vdec_thread_param *)args; ++ ot_vdec_stream stream; ++ printf("sample_comm_vdec_send_stream v4l2 \r\n"); ++ ++ td_s32 v4l2_fd = -1; ++ struct v4l2_capability cap; ++ struct v4l2_format fmt; ++ struct v4l2_requestbuffers req; ++ struct v4l2_buffer v4l2_buf; ++ enum v4l2_buf_type buf_type; ++ fd_set fds; ++ struct timeval tv; ++ td_u8 *v4l2_buffers[4] = {NULL}; ++ td_u32 buffer_count = 0; ++ td_u32 max_buffer_length = 0; ++ ++ prctl(PR_SET_NAME, "v4l2_to_vdec", 0, 0, 0); ++ ++ if (thread_param == NULL) { ++ sample_print("?????????!"); ++ return (td_void *)TD_FAILURE; ++ } ++ ++ sample_print("????v4l2????????: %s", thread_param->v4l2_device); ++ v4l2_fd = open(thread_param->v4l2_device, O_RDWR | O_NONBLOCK, 0); ++ if (v4l2_fd < 0) { ++ sample_print("?????????? %s: %s", ++ thread_param->v4l2_device, strerror(errno)); ++ return (td_void *)(TD_FAILURE); ++ } ++ ++ if (ioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) { ++ sample_print("VIDIOC_QUERYCAP????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { ++ sample_print("?????????????"); ++ goto v4l2_cleanup; ++ } ++ ++ memset(&fmt, 0, sizeof(fmt)); ++ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ fmt.fmt.pix.width = thread_param->width; ++ fmt.fmt.pix.height = thread_param->height; ++ fmt.fmt.pix.pixelformat = thread_param->pixel_format; ++ fmt.fmt.pix.field = V4L2_FIELD_ANY; ++ ++ if (ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt) < 0) { ++ sample_print("VIDIOC_S_FMT????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ struct v4l2_streamparm parm; ++ memset(&parm, 0, sizeof(parm)); ++ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ parm.parm.capture.timeperframe.numerator = 1; ++ parm.parm.capture.timeperframe.denominator = thread_param->fps; ++ if (ioctl(v4l2_fd, VIDIOC_S_PARM, &parm) < 0) { ++ sample_print("??????????????????: %s", strerror(errno)); ++ } ++ ++ memset(&req, 0, sizeof(req)); ++ req.count = 4; ++ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ req.memory = V4L2_MEMORY_MMAP; ++ ++ if (ioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { ++ sample_print("VIDIOC_REQBUFS????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ buffer_count = req.count; ++ max_buffer_length = 0; ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ v4l2_buf.index = i; ++ ++ if (ioctl(v4l2_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QUERYBUF????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ if (v4l2_buf.length > max_buffer_length) { ++ max_buffer_length = v4l2_buf.length; ++ } ++ ++ v4l2_buffers[i] = mmap(NULL, v4l2_buf.length, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, ++ v4l2_fd, ++ v4l2_buf.m.offset); ++ ++ if (v4l2_buffers[i] == MAP_FAILED) { ++ sample_print("mmap???: %s", strerror(errno)); ++ v4l2_buffers[i] = NULL; ++ goto v4l2_cleanup; ++ } ++ } ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ v4l2_buf.index = i; ++ ++ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QBUF????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ } ++ ++ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ if (ioctl(v4l2_fd, VIDIOC_STREAMON, &buf_type) < 0) { ++ sample_print("VIDIOC_STREAMON????: %s", strerror(errno)); ++ goto v4l2_cleanup; ++ } ++ ++ sample_print("v4l2???????????: %s, %dx%d@%llufps, ???: %c%c%c%c", ++ thread_param->v4l2_device, ++ thread_param->width, ++ thread_param->height, ++ thread_param->fps, ++ thread_param->pixel_format & 0xFF, ++ (thread_param->pixel_format >> 8) & 0xFF, ++ (thread_param->pixel_format >> 16) & 0xFF, ++ (thread_param->pixel_format >> 24) & 0xFF); ++ ++ while (thread_param->e_thread_ctrl == THREAD_CTRL_START) { ++ FD_ZERO(&fds); ++ FD_SET(v4l2_fd, &fds); ++ ++ tv.tv_sec = 2; ++ tv.tv_usec = 0; ++ ++ td_s32 r = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); ++ if (r == -1) { ++ if (errno == EINTR) continue; ++ sample_print("select????: %s", strerror(errno)); ++ break; ++ } ++ ++ if (r == 0) { ++ sample_print("select???"); ++ continue; ++ } ++ ++ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); ++ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ v4l2_buf.memory = V4L2_MEMORY_MMAP; ++ ++ if (ioctl(v4l2_fd, VIDIOC_DQBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_DQBUF????: %s", strerror(errno)); ++ continue; ++ } ++ ++ if (v4l2_buf.bytesused == 0) { ++ sample_print("????????"); ++ goto requeue_buffer; ++ } ++ ++ memset(&stream, 0, sizeof(ot_vdec_stream)); ++ stream.addr = v4l2_buffers[v4l2_buf.index]; ++ stream.len = v4l2_buf.bytesused; ++ stream.end_of_stream = TD_FALSE; ++ ++ struct timeval now; ++ gettimeofday(&now, NULL); ++ stream.pts = now.tv_sec * 1000000 + now.tv_usec; ++ ++ td_s32 s32Ret = ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, 30); ++ if (s32Ret != TD_SUCCESS) { ++ sample_print("?????VDEC???, ret=%#x", s32Ret); ++ } ++ ++requeue_buffer: ++ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { ++ sample_print("VIDIOC_QBUF????: %s", strerror(errno)); ++ break; ++ } ++ } ++ ++ memset(&stream, 0, sizeof(ot_vdec_stream)); ++ stream.end_of_stream = TD_TRUE; ++ ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, -1); ++ ++ sample_print("v4l2?????????"); ++ ++v4l2_cleanup: ++ if (v4l2_fd >= 0) { ++ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ioctl(v4l2_fd, VIDIOC_STREAMOFF, &buf_type); ++ } ++ ++ for (td_u32 i = 0; i < buffer_count; ++i) { ++ if (v4l2_buffers[i]) { ++ munmap(v4l2_buffers[i], max_buffer_length); ++ } ++ } ++ ++ if (v4l2_fd >= 0) { ++ close(v4l2_fd); ++ } ++ ++ return (td_void *)TD_SUCCESS; ++} ++#else + td_void *sample_comm_vdec_send_stream(td_void *args) + { + vdec_thread_param *thread_param = (vdec_thread_param *)args; +@@ -691,6 +919,7 @@ end1: + path = TD_NULL; + return (td_void *)TD_SUCCESS; + } ++#endif + + td_void sample_comm_vdec_cmd_not_circle_send(td_u32 chn_num, vdec_thread_param *vdec_send, + pthread_t *vdec_thread, td_u32 send_arr_len, td_u32 thread_arr_len) +diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c +index 5b66f54..8e999f6 100644 +--- a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c ++++ b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c +@@ -51,6 +51,7 @@ + #define MIPI_NUM 3 + #define OB_HEIGHT_END 32 + #define OB_HEIGHT_START 0 ++#define IMX347_OB_HEIGHT_END 20 + + typedef struct { + sample_vi_user_frame_info *user_frame_info; +@@ -111,6 +112,246 @@ static combo_dev_attr_t g_mipi_4lane_chn0_sensor_hy_s0603_10bit_8m_wdr2to1_attr + } + }; + ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_3840, HEIGHT_2160}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2592, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_dev2_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 2, WIDTH_2592, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_12BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_dev2_attr = { ++ .devno = 2, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_VC, ++ {0, 1, 2, 3, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_dev2_attr = { ++ .devno = 0, ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 5, 6, 7, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 0, /* dev0 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 2, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn1_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 1, /* dev1 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {1, 3, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn2_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 6, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn3_sensor_sc450ai_4m_nowdr_attr = { ++ .devno = 3, /* dev3 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {5, 7, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 0, /* dev0 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {0, 2, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn1_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 1, /* dev1 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {1, 3, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn2_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 2, /* dev2 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {4, 6, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ ++static combo_dev_attr_t g_mipi_2lane_chn3_sensor_sc450ai_2m_nowdr_attr = { ++ .devno = 3, /* dev3 */ ++ .input_mode = INPUT_MODE_MIPI, ++ .data_rate = MIPI_DATA_RATE_X1, ++ .img_rect = {0, 0, WIDTH_1920, HEIGHT_1080}, ++ .mipi_attr = { ++ DATA_TYPE_RAW_10BIT, ++ OT_MIPI_WDR_MODE_NONE, ++ {5, 7, -1, -1, -1, -1, -1, -1} ++ } ++}; ++ + static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_attr_t *combo_attr) + { + td_u32 ob_height = OB_HEIGHT_START; +@@ -125,10 +366,47 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), + &g_mipi_4lane_chn0_sensor_hy_s0603_10bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ //ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ break; + + default: + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), +- &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); + } + combo_attr->img_rect.height = combo_attr->img_rect.height + ob_height; + } +@@ -138,9 +416,21 @@ static td_void sample_comm_vi_get_mipi_ext_data_attr(sample_sns_type sns_type, e + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), + &g_mipi_ext_data_type_12bit_8m_nowdr_attr, sizeof(ext_data_type_t)); + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), ++ &g_mipi_ext_data_type_default_attr, sizeof(ext_data_type_t)); ++ break; + + default: + (td_void)memcpy_s(ext_data_attr, sizeof(ext_data_type_t), +@@ -163,7 +453,90 @@ static td_void sample_comm_vi_get_mipi_attr_by_dev_id(sample_sns_type sns_type, + &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); + } + break; +- ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ //ob_height = OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_nowdr_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ if (vi_dev == 0) { ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); ++ } else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_4lane_chn0_sensor_sc450ai_10bit_4m_wdr2to1_dev2_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ if (vi_dev == 0) { /* dev0 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 1) { /* dev1 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn1_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn2_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 3) { /* dev3 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn3_sensor_sc450ai_4m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ if (vi_dev == 0) { /* dev0 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn0_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 1) { /* dev1 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn1_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 2) { /* dev2 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn2_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ else if (vi_dev == 3) { /* dev3 */ ++ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), ++ &g_mipi_2lane_chn3_sensor_sc450ai_2m_nowdr_attr, sizeof(combo_dev_attr_t)); ++ } ++ break; + default: + (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), + &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); +@@ -240,6 +613,23 @@ td_void sample_comm_vi_get_size_by_sns_type(sample_sns_type sns_type, ot_size *s + size->width = WIDTH_3840; + size->height = HEIGHT_2160; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ size->width = WIDTH_3840; ++ size->height = HEIGHT_2160; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ size->width = WIDTH_2688; ++ size->height = HEIGHT_1520; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ size->width = WIDTH_2592; ++ size->height = HEIGHT_1520; ++ break; + + default: + size->width = WIDTH_1920; +@@ -256,6 +646,24 @@ td_u32 sample_comm_vi_get_obheight_by_sns_type(sample_sns_type sns_type) + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + ob_height = OB_HEIGHT_END; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ ob_height = OB_HEIGHT_END; ++ break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ ob_height = OB_HEIGHT_END; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ ob_height = IMX347_OB_HEIGHT_END; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ ob_height = OB_HEIGHT_START; ++ break; ++ + default: + break; + } +@@ -267,8 +675,17 @@ static td_u32 sample_comm_vi_get_pipe_num_by_sns_type(sample_sns_type sns_type) + { + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + return 1; + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: + return 2; /* 2 pipe */ + + default: +@@ -280,9 +697,18 @@ static ot_wdr_mode sample_comm_vi_get_wdr_mode_by_sns_type(sample_sns_type sns_t + { + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: + return OT_WDR_MODE_NONE; + + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: + return OT_WDR_MODE_2To1_LINE; + + default: +@@ -295,7 +721,7 @@ td_void sample_comm_vi_get_default_sns_info(sample_sns_type sns_type, sample_sns + sns_info->sns_type = sns_type; + sns_info->sns_clk_src = 0; + sns_info->sns_rst_src = 0; +- sns_info->bus_id = 2; /* i2c2 */ ++ sns_info->bus_id = 5; /* i2c5 */ + } + + td_void sample_comm_vi_get_default_mipi_info(sample_sns_type sns_type, sample_mipi_info *mipi_info) +diff --git a/smp/a55_linux/mpp/sample/gfbg/Makefile b/smp/a55_linux/mpp/sample/gfbg/Makefile +index c4ad611..ee7cb6e 100644 +--- a/smp/a55_linux/mpp/sample/gfbg/Makefile ++++ b/smp/a55_linux/mpp/sample/gfbg/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + SMP_SRCS := $(wildcard *.c) + TARGET := $(SMP_SRCS:%.c=%) + +-MPI_LIBS += $(REL_LIB)/libss_tde.so ++MPI_LIBS += -lss_tde + + TARGET_PATH := $(PWD) + +diff --git a/smp/a55_linux/mpp/sample/hnr/Makefile b/smp/a55_linux/mpp/sample/hnr/Makefile +index a457015..3a71a5c 100755 +--- a/smp/a55_linux/mpp/sample/hnr/Makefile ++++ b/smp/a55_linux/mpp/sample/hnr/Makefile +@@ -8,8 +8,8 @@ SMP_SRCS := $(wildcard $(PWD)/sample_hnr.c) + + ifeq ($(CONFIG_OT_ISP_HNR_SUPPORT), y) + CFLAGS += -DSAMPLE_HNR_SUPPORT +-MPI_LIBS += $(REL_LIB)/libss_pqp.so +-MPI_LIBS += $(REL_LIB)/libss_hnr.so ++MPI_LIBS += -lss_pqp ++MPI_LIBS += -lss_hnr + endif + + # compile linux or LITEOS +diff --git a/smp/a55_linux/mpp/sample/hnr/sample_hnr.c b/smp/a55_linux/mpp/sample/hnr/sample_hnr.c +index db2fabf..3df7490 100644 +--- a/smp/a55_linux/mpp/sample/hnr/sample_hnr.c ++++ b/smp/a55_linux/mpp/sample/hnr/sample_hnr.c +@@ -519,6 +519,10 @@ static td_s32 sample_hnr_start_venc_and_vo(ot_vpss_grp vpss_grp[], td_u32 grp_nu + + if (SENSOR0_TYPE == HY_S0603_MIPI_8M_30FPS_12BIT) { + g_venc_chn_param.size = PIC_3840X2160; ++ } else if (SENSOR0_TYPE == SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT) { ++ g_venc_chn_param.size = PIC_2560X1440; ++ } else if (SENSOR0_TYPE == OV_OS08A20_MIPI_8M_30FPS_12BIT) { ++ g_venc_chn_param.size = PIC_3840X2160; + } else { + g_venc_chn_param.size = PIC_1080P; + } +@@ -765,7 +769,7 @@ static td_s32 sample_hnr_set_blc(ot_vi_pipe vi_pipe, sample_sns_type sns_type) + } + } + +- if (sns_type == HY_S0603_MIPI_8M_30FPS_12BIT) { ++ if ((sns_type == HY_S0603_MIPI_8M_30FPS_12BIT) || (sns_type == SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT)) { + black_level_attr.black_level_mode = OT_ISP_BLACK_LEVEL_MODE_DYNAMIC; + } + +diff --git a/smp/a55_linux/mpp/sample/smp_linux.mak b/smp/a55_linux/mpp/sample/smp_linux.mak +index 19cd519..f07923d 100644 +--- a/smp/a55_linux/mpp/sample/smp_linux.mak ++++ b/smp/a55_linux/mpp/sample/smp_linux.mak +@@ -4,7 +4,7 @@ OBJS := $(SMP_SRCS:%.c=%.o) + + CFLAGS += $(COMM_INC) + +-MPI_LIBS += $(REL_LIB)/libss_hdmi.so ++MPI_LIBS += -lss_hdmi + MPI_LIBS += $(LIBS_LD_CFLAGS) + + .PHONY : clean all +@@ -12,7 +12,7 @@ MPI_LIBS += $(LIBS_LD_CFLAGS) + all: $(TARGET) + + $(TARGET):$(COMM_OBJ) $(OBJS) +- $(CC) $(CFLAGS) -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) $(REL_LIB)/libsecurec.so -Wl,--end-group ++ $(CC) $(CFLAGS) -L$(REL_LIB) -L$(REL_LIB)/svp_npu -lpthread -lm -o $(TARGET_PATH)/$@ $^ -Wl,-rpath=$$ORIGIN/../lib -Wl,-rpath-link=$(REL_LIB) -Wl,-rpath-link=$(REL_LIB)/svp_npu -Wl,--disable-new-dtags -Wl,--start-group $(MPI_LIBS) $(SDK_LIB) $(SENSOR_LIBS) $(INIPARSER_LIB) -lsecurec -Wl,--end-group + + clean: + @rm -f $(TARGET_PATH)/$(TARGET) +diff --git a/smp/a55_linux/mpp/sample/snap/Makefile b/smp/a55_linux/mpp/sample/snap/Makefile +index b4d617e..f2f4324 100644 +--- a/smp/a55_linux/mpp/sample/snap/Makefile ++++ b/smp/a55_linux/mpp/sample/snap/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + ########### SRCS & INC ############ + SMP_SRCS := $(wildcard $(PWD)/*.c) + +-MPI_LIBS += $(REL_LIB)/libss_snap.so ++MPI_LIBS += -lss_snap + + TARGET := sample_snap + +diff --git a/smp/a55_linux/mpp/sample/svp/Makefile.param b/smp/a55_linux/mpp/sample/svp/Makefile.param +index 3983a2c..de8a735 100644 +--- a/smp/a55_linux/mpp/sample/svp/Makefile.param ++++ b/smp/a55_linux/mpp/sample/svp/Makefile.param +@@ -5,16 +5,15 @@ COMMON_DIR:=$(PWD)/../../common + AUDIO_ADP_DIR:=$(PWD)/../../audio/adp + include ../../Makefile.param + +-MPI_LIBS += $(REL_LIB)/libss_ive.so +-MPI_LIBS += $(REL_LIB)/libss_md.so +-MPI_LIBS += $(REL_LIB)/libss_mau.so +-MPI_LIBS += $(REL_LIB)/libss_dpu_rect.so +-MPI_LIBS += $(REL_LIB)/libss_dpu_match.so ++MPI_LIBS += -lss_ive ++MPI_LIBS += -lss_md ++MPI_LIBS += -lss_mau ++MPI_LIBS += -lss_dpu_rect ++MPI_LIBS += -lss_dpu_match + ifneq ($(CONFIG_DRIVER_SPACE_TYPE),user_space) +- MPI_LIBS += $(REL_LIB)/libss_dsp.so ++ MPI_LIBS += -lss_dsp + endif +-MPI_LIBS += $(REL_LIB)/svp_npu/libsvp_acl.so +-MPI_LIBS += -L$(REL_LIB)/svp_npu -lprotobuf-c ++MPI_LIBS += -lsvp_acl -lprotobuf-c + CFLAGS += -I$(PWD)/../common + CFLAGS += -I$(REL_INC)/svp_npu + CFLAGS += -fstack-protector-strong +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c +index 3b3b289..b2eb9d8 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c +@@ -61,6 +61,22 @@ static td_s32 sample_common_svp_get_pic_type_by_sns_type(sample_sns_type sns_typ + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + size[0] = PIC_3840X2160; + break; ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT: ++ case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: ++ size[0] = PIC_3840X2160; ++ break; ++ case OV_OS04A10_MIPI_4M_30FPS_12BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT: ++ case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: ++ case SC450AI_2L_MIPI_4M_30FPS_10BIT: ++ size[0] = PIC_2688X1520; ++ break; ++ case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: ++ size[0] = PIC_2592X1520; ++ break; ++ case SC450AI_2L_MIPI_2M_30FPS_10BIT: ++ size[0] = PIC_1080P; ++ break; + default: + size[0] = PIC_3840X2160; + break; +@@ -428,7 +444,7 @@ static td_void sample_common_svp_stop_vpss(td_s32 vpss_grp_cnt, td_u32 vpss_chn_ + } + } + +-static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) ++td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) + { + ot_rect def_disp_rect = {0, 0, 1920, 1080}; + ot_size def_img_size = {1920, 1080}; +@@ -441,7 +457,7 @@ static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) + vo_cfg->vo_dev = SAMPLE_VO_DEV_UHD; + + vo_cfg->vo_intf_type = OT_VO_INTF_HDMI; +- vo_cfg->intf_sync = OT_VO_OUT_1080P30; ++ vo_cfg->intf_sync = OT_VO_OUT_1080P60; + vo_cfg->bg_color = COLOR_RGB_BLACK; + vo_cfg->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vo_cfg->disp_rect = def_disp_rect; +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h +index 626a2d6..dd86d96 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h +@@ -60,6 +60,8 @@ typedef enum { + + typedef struct { + ot_point point[OT_POINT_NUM]; ++ td_float score; ++ td_u16 class_id; + } ot_sample_svp_rect; + + typedef struct { +diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c +index 3f811f0..469ff32 100644 +--- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c ++++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c +@@ -999,6 +999,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + td_float *y_min = TD_NULL; + td_float *x_max = TD_NULL; + td_float *y_max = TD_NULL; ++ td_float *score = TD_NULL; ++ td_float *class_id = TD_NULL; + td_u32 roi_offset = info->roi_offset; + td_u32 i; + +@@ -1019,6 +1021,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + y_min = x_min + stride / sizeof(td_float); + x_max = y_min + stride / sizeof(td_float); + y_max = x_max + stride / sizeof(td_float); ++ score = y_max + stride / sizeof(td_float); ++ class_id = score + stride / sizeof(td_float); + + for (i = 0; i < rect_info->num; i++) { + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)((td_float)x_min[roi_offset] / +@@ -1040,6 +1044,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; ++ rect_info->rect[i].score = (td_float)((td_float)score[roi_offset]); ++ rect_info->rect[i].class_id = (td_u16)((td_float)class_id[roi_offset]); + roi_offset++; + } + return TD_SUCCESS; +@@ -1319,6 +1325,9 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) + { + td_s32 ret; ++ td_u32 i; ++ td_float max_confidence = 0.0f; ++ td_u32 max_index = 0; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); +@@ -1341,6 +1350,19 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + ret = sample_svp_npu_get_roi(task, detection_info, proc_frame, show_frame, rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi failed!\n"); ++ if (rect_info->num > 0) { ++ for (i = 0; i < rect_info->num; i++) { ++ if (rect_info->rect[i].score > max_confidence) { ++ max_confidence = rect_info->rect[i].score; ++ max_index = i; ++ } ++ } ++ ++ if (rect_info->num > 1) { ++ rect_info->rect[0] = rect_info->rect[max_index]; ++ rect_info->num = 1; ++ } ++ } + + return TD_SUCCESS; + } +diff --git a/smp/a55_linux/mpp/sample/tde/Makefile b/smp/a55_linux/mpp/sample/tde/Makefile +index bf925b5..533ee73 100644 +--- a/smp/a55_linux/mpp/sample/tde/Makefile ++++ b/smp/a55_linux/mpp/sample/tde/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.param + SMP_SRCS := $(wildcard *.c) + TARGET := $(SMP_SRCS:%.c=%) + +-MPI_LIBS += $(REL_LIB)/libss_tde.so ++MPI_LIBS += -lss_tde + + TARGET_PATH := $(PWD) + +diff --git a/smp/a55_linux/mpp/sample/vio/sample_vio.c b/smp/a55_linux/mpp/sample/vio/sample_vio.c +index 9c29f05..627bb16 100644 +--- a/smp/a55_linux/mpp/sample/vio/sample_vio.c ++++ b/smp/a55_linux/mpp/sample/vio/sample_vio.c +@@ -63,7 +63,7 @@ static td_u16 g_lmf_coef[128] = { + static sample_vo_cfg g_vo_cfg = { + .vo_dev = SAMPLE_VO_DEV_UHD, + .vo_intf_type = OT_VO_INTF_HDMI, +- .intf_sync = OT_VO_OUT_1080P30, ++ .intf_sync = OT_VO_OUT_1080P60, + .bg_color = COLOR_RGB_BLACK, + .pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, + .disp_rect = {0, 0, 1920, 1080}, +diff --git a/smp/a55_linux/mpp/sample/vo/sample_vo.c b/smp/a55_linux/mpp/sample/vo/sample_vo.c +index b2db0cb..1baa0d5 100644 +--- a/smp/a55_linux/mpp/sample/vo/sample_vo.c ++++ b/smp/a55_linux/mpp/sample/vo/sample_vo.c +@@ -345,6 +345,184 @@ static mipi_tx_cmd_info g_cmd_info_1200x1920[CMD_COUNT_1200X1920] = { + {{0, 0, 0, 0x23, 0x0029, NULL}, USLEEP_60000}, + }; + ++#define CMD_DATA_COUNT_800X1280_ST 48 ++static unsigned char g_cmd_data_800x1280_st[CMD_DATA_COUNT_800X1280_ST][39] = { ++{0xE0,0xAB,0xBA}, ++{0xE1,0xBA,0xAB}, ++{0xB1,0x10,0x01,0x47,0xFF}, ++{0xB2,0x0c,0x0e,0x04,0x14,0x14,0x14}, ++{0xB3,0x56,0xD3,0x00}, ++{0xB4,0x22,0x30,0x04}, ++{0xB6,0xb0,0x00,0x00,0x10,0x00,0x10,0x00}, ++{0xB7,0x0E,0x00,0xFF,0x08,0x08,0xFF,0xFF,0x00}, ++{0xB8,0x05,0x12,0x29,0x49,0x48,0x00,0x00}, ++{0xB9,0x4d,0x42,0x38,0x31,0x33,0x27,0x2F,0x1B,0x36,0x35,0x35,0x53,0x41,0x49,0x3D,0x3d,0x33,0x29,0x26,0x4c,0x42,0x39,0x31,0x33,0x27,0x2F,0x1B,0x36,0x35,0x35,0x53,0x41,0x49,0x3D,0x3d,0x33,0x29,0x26}, ++{0xBA,0x00,0x00,0x00,0x44,0x24,0x00,0x00,0x00}, ++{0xBB,0x76,0x00,0x00}, ++{0xBC,0x00,0x00}, ++{0xBD,0xFF,0x00,0x00,0x00,0x00}, ++{0xC0,0x98,0x76,0x12,0x34,0x33,0x33,0x44,0x44,0x06,0x04,0x8A,0x04,0x0F,0x00,0x00,0x00}, ++{0xC1,0x53,0x94,0x02,0x85,0x06,0x04,0x8A,0x04,0x54,0x00}, ++{0xC2,0x37,0x09,0x08,0x89,0x08,0x10,0x22,0x21,0x44,0xBB,0x18,0x00}, ++{0xC3,0x9C,0x1D,0x1E,0x1F,0x10,0x12,0x0C,0x0E,0x05,0x24,0x24,0x24,0x24,0x24,0x24,0x07,0x24,0x24,0x24,0x24,0x24,0x24}, ++{0xC4,0x1C,0x1D,0x1E,0x1F,0x11,0x13,0x0D,0x0F,0x04,0x24,0x24,0x24,0x24,0x24,0x24,0x06,0x24,0x24,0x24,0x24,0x24,0x24}, ++{0xC5,0xE8,0x85,0x76}, ++{0xC6,0x20,0x20}, ++{0xC7,0x41,0x01,0x0D,0x11,0x09,0x15,0x19,0x4F,0x10,0xD7,0xCF,0x19,0x1B,0x1D,0x03,0x02,0x25,0x30,0x00,0x03,0xFF,0x00}, ++{0xC8,0x61,0x00,0x31,0x42,0x54,0x16}, ++{0xC9,0xA1,0x22,0xFF,0xCd,0x23}, ++{0xCA,0x4B,0x43}, ++{0xCC,0x2E,0x02,0x04,0x08}, ++{0xCD,0x0E,0x64,0x64,0x20,0x1E,0x6B,0x06,0x83}, ++{0xD0,0x27,0x10,0x80}, ++{0xD1,0x00,0x0D,0xFF,0x0F}, ++{0xD2,0xE3,0x2B,0x38,0x00}, ++{0xD4,0x00,0x01,0x00,0x0E,0x04,0x44,0x08,0x10,0x00,0x07,0x00}, ++{0xD6,0x00,0x00}, ++{0xD7,0x00,0x00,0x00,0x00}, ++{0xE4,0x08,0x55,0x03}, ++{0xE6,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, ++{0xE7,0x00,0x00,0x00}, ++{0xE8,0xD5,0xFF,0xFF,0xFF,0x00,0x00,0x00}, ++{0xF0,0x12,0x03,0x20,0x00,0xFF}, ++{0xF1,0xA6,0xC8,0xEA,0xE6,0xE4,0xCC,0xE4,0xBE,0xF0,0xB2,0xAA,0xC7,0xFF,0x66,0x98,0xE3,0x87,0xC8,0x99,0xC8,0x8C,0xBE,0x96,0x91,0x8F,0xFF}, ++{0xF4,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF5,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF6,0xFF,0xFE,0xFC,0xFA,0xF8,0xF4,0xF0,0xE8,0xE0,0xD0,0xC0,0xA0,0x80,0x7F,0x5F,0x3F,0x2F,0x1F,0x17,0x0F,0x0B,0x07,0x05,0x03,0x01,0x00}, ++{0xF7,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, ++{0xFA,0x00,0x84,0x12,0x21,0x48,0x48,0x21,0x12,0x84,0x69,0x69,0x5A,0xA5,0x96,0x96,0xA5,0x5A,0xB7,0xDE,0xED,0x7B,0x7B,0xED,0xDE,0xB7}, ++{0xFB,0x00,0x12,0x0F,0xFF,0xFF,0xFF,0x00,0x38,0x40,0x08,0x70,0x0B,0x40,0x19,0x50,0x21,0xC0,0x27,0x60,0x2D,0x00,0x00,0x0F}, ++{0xE3,0x20,0x21}, ++}; ++#define UDELAY_50 50 ++#define CMD_COUNT_800X1280 56 ++static mipi_tx_cmd_info g_cmd_info_800x1280[CMD_COUNT_800X1280] = { ++ /* {devno work_mode lp_clk_en data_type cmd_size cmd}, usleep_value */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[0]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[1]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00B0, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[2]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x07, g_cmd_data_800x1280_st[3]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[4]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[5]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00B5, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[6]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[7]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[8]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x27, g_cmd_data_800x1280_st[9]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[10]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[11]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[12]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[13]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00BE, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x11, g_cmd_data_800x1280_st[14]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0b, g_cmd_data_800x1280_st[15]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0d, g_cmd_data_800x1280_st[16]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[17]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[18]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[19]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[20]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x17, g_cmd_data_800x1280_st[21]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x07, g_cmd_data_800x1280_st[22]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[23]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[24]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[25]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[26]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[27]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[28]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[29]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x0c, g_cmd_data_800x1280_st[30]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x00D5, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[31]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x05, g_cmd_data_800x1280_st[32]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[33]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x09, g_cmd_data_800x1280_st[34]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x04, g_cmd_data_800x1280_st[35]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[36]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0xFFE9, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x06, g_cmd_data_800x1280_st[37]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[38]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x13, 0x03F3, TD_NULL}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[39]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[40]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1b, g_cmd_data_800x1280_st[41]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[42]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[43]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x08, g_cmd_data_800x1280_st[44]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x1a, g_cmd_data_800x1280_st[45]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x18, g_cmd_data_800x1280_st[46]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x29, 0x03, g_cmd_data_800x1280_st[47]}, UDELAY_50}, /* 0: 0 cmd data index */ ++ {{0, 0, 1, 0x05, 0x0011, NULL}, 250000}, ++ {{0, 0, 1, 0x05, 0x0029, NULL}, 50000}, ++}; ++/* VO: USER 800x1280_60, TX: USER 800x1280 */ ++static const sample_vo_mipi_tx_cfg g_vo_tx_cfg_800x1280_user = { ++ .vo_config = { ++ .vo_dev = SAMPLE_VO_DEV_UHD, ++ .vo_intf_type = OT_VO_INTF_MIPI, ++ .intf_sync = OT_VO_OUT_USER, ++ .bg_color = COLOR_RGB_BLUE, ++ .pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, ++ .disp_rect = {0, 0, 800, 1280}, ++ .image_size = {800, 1280}, ++ .vo_part_mode = OT_VO_PARTITION_MODE_SINGLE, ++ .dis_buf_len = 3, /* 3: def buf len for single */ ++ .dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8, ++ .vo_mode = VO_MODE_1MUX, ++ .compress_mode = OT_COMPRESS_MODE_NONE, ++ ++ .sync_info = {0, 1, 1, 1280, 21, 16, 800, 68, 48, 1, 1, 1, 1, 20, 6, 0, 0, 0}, ++ //.sync_info = {0, 1, 1, 1280, 21, 16, 800, 68, 48, 1, 1, 1, 1, 20, 6, 0, 0, 0}, ++ .user_sync = { ++ .user_sync_attr = { ++ .clk_src = OT_VO_CLK_SRC_PLL, ++ .vo_pll = { /* if hdmi, set it by pixel clk and div mode */ ++ .fb_div = 34, /* 72 fb div */ ++ .frac = 0, ++ .ref_div = 1, /* 1 ref div */ ++ .post_div1 = 4, /* 6 post div1 */ ++ .post_div2 = 3, /* 2 post div2 */ ++ }, ++ }, ++ .pre_div = 1, /* if hdmi, set it by pixel clk */ ++ .dev_div = 1, /* if rgb, set it by serial mode */ ++ .clk_reverse_en = TD_FALSE, ++ }, ++ .dev_frame_rate = SAMPLE_VO_DEV_FRAME_RATE, ++ }, ++ .tx_config = { ++ /* for combo dev config */ ++ .intf_sync = OT_MIPI_TX_OUT_USER, ++ ++ /* for screen cmd */ ++ .cmd_count = CMD_COUNT_800X1280, ++ .cmd_info = g_cmd_info_800x1280, ++ ++ /* for user sync */ ++ .combo_dev_cfg = { ++ .devno = 0, ++ .lane_id = {0, 1, 2, 3}, ++ .out_mode = OUT_MODE_DSI_VIDEO, ++ .out_format = OUT_FORMAT_RGB_24BIT, ++ .video_mode = BURST_MODE, ++ .sync_info = { ++ .hsa_pixels = 20, /* 20 pixel */ ++ .hbp_pixels = 48, /* 48 pixel */ ++ .hact_pixels = 800, /* 800 pixel */ ++ .hfp_pixels = 48, /* 48 pixel */ ++ .vsa_lines = 6, /* 6 line */ ++ .vbp_lines = 15, /* 15 line */ ++ .vact_lines = 1280, /* 1280 line */ ++ .vfp_lines = 16, /* 16 line */ ++ }, ++ .phy_data_rate = 435, /* 435 Mbps */ ++ .pixel_clk = 68000, /* 68000 KHz */ ++ }, ++ }, ++}; ++ + /* VO: USER 1200x1920_60, TX: USER 1200x1920 */ + static const sample_vo_mipi_tx_cfg g_vo_tx_cfg_1200x1920_user = { + .vo_config = { +@@ -630,17 +808,22 @@ static td_s32 sample_vo_mipi_tx_1200x1920_user(td_void) + return sample_vo_mipi_tx(&g_vo_tx_cfg_1200x1920_user); + } + ++static td_s32 sample_vo_mipi_tx_800x1280_user(td_void) ++{ ++ return sample_vo_mipi_tx(&g_vo_tx_cfg_800x1280_user); ++} ++ + static void sample_vo_usage(const char *name) + { + printf("usage : %s \n", name); + printf("index:\n"); +- printf("\t0: vo dhd0 mipi_tx USER 1200x1920@60 output.\n"); ++ printf("\t0: vo dhd0 mipi_tx USER 800x1280@60 output.\n"); + } + + static td_s32 sample_vo_execute_case(td_s32 index) + { + if (index == 0) { +- return sample_vo_mipi_tx_1200x1920_user(); ++ return sample_vo_mipi_tx_800x1280_user(); + } + + sample_print("the index %d is invalid!\n", index); diff --git a/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-zsks-demo.patch b/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-zsks-demo.patch deleted file mode 100755 index 7de9cffd36a82095910acd011f0ec119d2c6d95a..0000000000000000000000000000000000000000 --- a/vendor/zsks/patch/gcc/0001-support-USB-Camera-and-zsks-demo.patch +++ /dev/null @@ -1,558 +0,0 @@ -From 013c6daae38a3ee9dd2ed98479b2db209ec589e0 Mon Sep 17 00:00:00 2001 -From: wgm2022 <1480559020@qq.com> -Date: Wed, 31 Dec 2025 10:58:23 +0800 -Subject: [PATCH] support USB Camera and zsks demo - ---- - smp/a55_linux/mpp/sample/common/Makefile | 2 + - smp/a55_linux/mpp/sample/common/sample_comm.h | 7 + - .../mpp/sample/common/sample_comm_isp.c | 21 ++ - .../mpp/sample/common/sample_comm_vdec.c | 229 ++++++++++++++++++ - .../mpp/sample/common/sample_comm_vi.c | 28 ++- - .../mpp/sample/svp/common/sample_common_svp.c | 4 +- - .../mpp/sample/svp/common/sample_common_svp.h | 2 + - .../svp/common/sample_common_svp_npu_model.c | 22 ++ - 8 files changed, 311 insertions(+), 4 deletions(-) - -diff --git a/smp/a55_linux/mpp/sample/common/Makefile b/smp/a55_linux/mpp/sample/common/Makefile -index 502ec11..3c5db63 100644 ---- a/smp/a55_linux/mpp/sample/common/Makefile -+++ b/smp/a55_linux/mpp/sample/common/Makefile -@@ -1,6 +1,8 @@ - param_file=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))/../Makefile.param - include $(param_file) - -+CFLAGS += -fPIC -+ - .PHONY : clean all - all:$(COMM_OBJ) - -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm.h b/smp/a55_linux/mpp/sample/common/sample_comm.h -index cc50e0c..c8a96e5 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm.h -+++ b/smp/a55_linux/mpp/sample/common/sample_comm.h -@@ -235,6 +235,7 @@ typedef enum { - OV_OS08A20_MIPI_8M_30FPS_12BIT, - OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1, - OV_OS04A10_MIPI_4M_30FPS_12BIT, -+ OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1, - SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT, - SC450AI_MIPI_4M_30FPS_10BIT, - SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1, -@@ -546,6 +547,12 @@ typedef struct { - td_u64 last_time; - td_u64 time_gap; - td_u64 fps; -+# ifdef USE_USB_CAMERA -+ td_char *v4l2_device; -+ td_u32 width; -+ td_u32 height; -+ td_u32 pixel_format; -+# endif - } vdec_thread_param; - - typedef struct { -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -index 982efa3..0d86d9a 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_isp.c -@@ -53,6 +53,7 @@ static ot_isp_sns_type g_sns_type[OT_VI_MAX_PIPE_NUM] = {(ot_isp_sns_type)SNS_TY - static pthread_t g_isp_pid[OT_VI_MAX_DEV_NUM] = {0}; - - extern ot_isp_sns_obj g_sns_hy_s0603_obj; -+extern ot_isp_sns_obj g_sns_os04a10_obj; - - /* IspPub attr */ - static ot_isp_pub_attr g_isp_pub_attr_hy_s0603_mipi_8m_30fps = { -@@ -130,6 +131,21 @@ static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps = { - }, - }; - -+static ot_isp_pub_attr g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1 = { -+ {0, 0, WIDTH_2688, HEIGHT_1520}, -+ {WIDTH_2688, HEIGHT_1520}, -+ 30, -+ OT_ISP_BAYER_RGGB, -+ OT_WDR_MODE_2To1_LINE, -+ 0, -+ 0, -+ 0, -+ { -+ 0, -+ {0, 0, 2688, 1520}, -+ }, -+}; -+ - static ot_isp_pub_attr g_isp_pub_attr_imx347_slave_mipi_4m_30fps = { - {0, 20, WIDTH_2592, HEIGHT_1520}, - {WIDTH_2592, HEIGHT_1520}, -@@ -228,6 +244,10 @@ td_s32 sample_comm_isp_get_pub_attr_by_sns(sample_sns_type sns_type, ot_isp_pub_ - (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), - &g_isp_pub_attr_os04a10_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); - break; -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), -+ &g_isp_pub_attr_os04a10_mipi_4m_30fps_wdr2to1, sizeof(ot_isp_pub_attr)); -+ break; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - (td_void)memcpy_s(pub_attr, sizeof(ot_isp_pub_attr), - &g_isp_pub_attr_imx347_slave_mipi_4m_30fps, sizeof(ot_isp_pub_attr)); -@@ -267,6 +287,7 @@ ot_isp_sns_obj *sample_comm_isp_get_sns_obj(sample_sns_type sns_type) - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - return &g_sns_os08a20_obj; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return &g_sns_os04a10_obj; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - return &g_sns_imx347_slave_obj; -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -index a0c9ad9..517b6d3 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_vdec.c -@@ -32,6 +32,17 @@ - #include - #include "sample_comm.h" - -+#ifdef USE_USB_CAMERA -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#endif -+ - #define SEND_STREAM_CNT 5 - #define VDEC_SECOND 1000000 - #define SAMPLE_VDEC_LOW_DELAY_LINE_CNT 16 -@@ -633,6 +644,223 @@ td_s32 sample_comm_vdec_check_send_stream_param(vdec_thread_param *thread_param, - return TD_SUCCESS; - } - -+ -+#ifdef USE_USB_CAMERA -+ -+td_void *sample_comm_vdec_send_stream(td_void *args) -+{ -+ printf("vdec send stream thread start\n"); -+ -+ vdec_thread_param *thread_param = (vdec_thread_param *)args; -+ ot_vdec_stream stream; -+ printf("sample_comm_vdec_send_stream v4l2 \r\n"); -+ -+ td_s32 v4l2_fd = -1; -+ struct v4l2_capability cap; -+ struct v4l2_format fmt; -+ struct v4l2_requestbuffers req; -+ struct v4l2_buffer v4l2_buf; -+ enum v4l2_buf_type buf_type; -+ fd_set fds; -+ struct timeval tv; -+ td_u8 *v4l2_buffers[4] = {NULL}; -+ td_u32 buffer_count = 0; -+ td_u32 max_buffer_length = 0; -+ -+ prctl(PR_SET_NAME, "v4l2_to_vdec", 0, 0, 0); -+ -+ if (thread_param == NULL) { -+ sample_print("̲߳Ϊ!"); -+ return (td_void *)TD_FAILURE; -+ } -+ -+ sample_print("v4l2ͷɼ: %s", thread_param->v4l2_device); -+ v4l2_fd = open(thread_param->v4l2_device, O_RDWR | O_NONBLOCK, 0); -+ if (v4l2_fd < 0) { -+ sample_print("޷ͷ %s: %s", -+ thread_param->v4l2_device, strerror(errno)); -+ return (td_void *)(TD_FAILURE); -+ } -+ -+ if (ioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) { -+ sample_print("VIDIOC_QUERYCAP: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { -+ sample_print("豸֧ʽ"); -+ goto v4l2_cleanup; -+ } -+ -+ memset(&fmt, 0, sizeof(fmt)); -+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ fmt.fmt.pix.width = thread_param->width; -+ fmt.fmt.pix.height = thread_param->height; -+ fmt.fmt.pix.pixelformat = thread_param->pixel_format; -+ fmt.fmt.pix.field = V4L2_FIELD_ANY; -+ -+ if (ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt) < 0) { -+ sample_print("VIDIOC_S_FMT: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ struct v4l2_streamparm parm; -+ memset(&parm, 0, sizeof(parm)); -+ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ parm.parm.capture.timeperframe.numerator = 1; -+ parm.parm.capture.timeperframe.denominator = thread_param->fps; -+ if (ioctl(v4l2_fd, VIDIOC_S_PARM, &parm) < 0) { -+ sample_print("֡ʧܣʹĬֵ: %s", strerror(errno)); -+ } -+ -+ memset(&req, 0, sizeof(req)); -+ req.count = 4; -+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ req.memory = V4L2_MEMORY_MMAP; -+ -+ if (ioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { -+ sample_print("VIDIOC_REQBUFS: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ buffer_count = req.count; -+ max_buffer_length = 0; -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ v4l2_buf.index = i; -+ -+ if (ioctl(v4l2_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QUERYBUF: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ if (v4l2_buf.length > max_buffer_length) { -+ max_buffer_length = v4l2_buf.length; -+ } -+ -+ v4l2_buffers[i] = mmap(NULL, v4l2_buf.length, -+ PROT_READ | PROT_WRITE, -+ MAP_SHARED, -+ v4l2_fd, -+ v4l2_buf.m.offset); -+ -+ if (v4l2_buffers[i] == MAP_FAILED) { -+ sample_print("mmapʧ: %s", strerror(errno)); -+ v4l2_buffers[i] = NULL; -+ goto v4l2_cleanup; -+ } -+ } -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ v4l2_buf.index = i; -+ -+ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QBUF: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ } -+ -+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ if (ioctl(v4l2_fd, VIDIOC_STREAMON, &buf_type) < 0) { -+ sample_print("VIDIOC_STREAMON: %s", strerror(errno)); -+ goto v4l2_cleanup; -+ } -+ -+ sample_print("v4l2ͷ: %s, %dx%d@%llufps, ʽ: %c%c%c%c", -+ thread_param->v4l2_device, -+ thread_param->width, -+ thread_param->height, -+ thread_param->fps, -+ thread_param->pixel_format & 0xFF, -+ (thread_param->pixel_format >> 8) & 0xFF, -+ (thread_param->pixel_format >> 16) & 0xFF, -+ (thread_param->pixel_format >> 24) & 0xFF); -+ -+ while (thread_param->e_thread_ctrl == THREAD_CTRL_START) { -+ FD_ZERO(&fds); -+ FD_SET(v4l2_fd, &fds); -+ -+ tv.tv_sec = 2; -+ tv.tv_usec = 0; -+ -+ td_s32 r = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); -+ if (r == -1) { -+ if (errno == EINTR) continue; -+ sample_print("select: %s", strerror(errno)); -+ break; -+ } -+ -+ if (r == 0) { -+ sample_print("selectʱ"); -+ continue; -+ } -+ -+ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); -+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ v4l2_buf.memory = V4L2_MEMORY_MMAP; -+ -+ if (ioctl(v4l2_fd, VIDIOC_DQBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_DQBUF: %s", strerror(errno)); -+ continue; -+ } -+ -+ if (v4l2_buf.bytesused == 0) { -+ sample_print("յ֡"); -+ goto requeue_buffer; -+ } -+ -+ memset(&stream, 0, sizeof(ot_vdec_stream)); -+ stream.addr = v4l2_buffers[v4l2_buf.index]; -+ stream.len = v4l2_buf.bytesused; -+ stream.end_of_stream = TD_FALSE; -+ -+ struct timeval now; -+ gettimeofday(&now, NULL); -+ stream.pts = now.tv_sec * 1000000 + now.tv_usec; -+ -+ td_s32 s32Ret = ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, 30); -+ if (s32Ret != TD_SUCCESS) { -+ sample_print("͵VDECʧ, ret=%#x", s32Ret); -+ } -+ -+requeue_buffer: -+ if (ioctl(v4l2_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { -+ sample_print("VIDIOC_QBUF: %s", strerror(errno)); -+ break; -+ } -+ } -+ -+ memset(&stream, 0, sizeof(ot_vdec_stream)); -+ stream.end_of_stream = TD_TRUE; -+ ss_mpi_vdec_send_stream(thread_param->chn_id, &stream, -1); -+ -+ sample_print("v4l2ɼ߳˳"); -+ -+v4l2_cleanup: -+ if (v4l2_fd >= 0) { -+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ ioctl(v4l2_fd, VIDIOC_STREAMOFF, &buf_type); -+ } -+ -+ for (td_u32 i = 0; i < buffer_count; ++i) { -+ if (v4l2_buffers[i]) { -+ munmap(v4l2_buffers[i], max_buffer_length); -+ } -+ } -+ -+ if (v4l2_fd >= 0) { -+ close(v4l2_fd); -+ } -+ -+ return (td_void *)TD_SUCCESS; -+} -+#else - td_void *sample_comm_vdec_send_stream(td_void *args) - { - vdec_thread_param *thread_param = (vdec_thread_param *)args; -@@ -691,6 +919,7 @@ end1: - path = TD_NULL; - return (td_void *)TD_SUCCESS; - } -+#endif - - td_void sample_comm_vdec_cmd_not_circle_send(td_u32 chn_num, vdec_thread_param *vdec_send, - pthread_t *vdec_thread, td_u32 send_arr_len, td_u32 thread_arr_len) -diff --git a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -index 5be7e63..8e999f6 100644 ---- a/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -+++ b/smp/a55_linux/mpp/sample/common/sample_comm_vi.c -@@ -172,6 +172,18 @@ static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_dev2_att - } - }; - -+static combo_dev_attr_t g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr = { -+ .devno = 0, -+ .input_mode = INPUT_MODE_MIPI, -+ .data_rate = MIPI_DATA_RATE_X1, -+ .img_rect = {0, 0, WIDTH_2688, HEIGHT_1520}, -+ .mipi_attr = { -+ DATA_TYPE_RAW_10BIT, -+ OT_MIPI_WDR_MODE_VC, -+ {0, 1, 2, 3, -1, -1, -1, -1} -+ } -+}; -+ - static combo_dev_attr_t g_mipi_4lane_chn0_sensor_imx347_slave_12bit_4m_nowdr_attr = { - .devno = 0, - .input_mode = INPUT_MODE_MIPI, -@@ -364,10 +376,16 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os08a20_12bit_8m_wdr2to1_attr, sizeof(combo_dev_attr_t)); - break; -- case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ //ob_height = OB_HEIGHT_END; - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); - break; -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ ob_height = OB_HEIGHT_END; -+ (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -+ &g_mipi_4lane_chn0_sensor_os04a10_10bit_4m_wdr2to1_attr, sizeof(combo_dev_attr_t)); -+ break; - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - ob_height = IMX347_OB_HEIGHT_END; - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -@@ -388,7 +406,7 @@ static td_void sample_comm_vi_get_mipi_attr(sample_sns_type sns_type, combo_dev_ - - default: - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), -- &g_mipi_4lane_chn0_sensor_hy_s0603_12bit_8m_nowdr_attr, sizeof(combo_dev_attr_t)); -+ &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); - } - combo_attr->img_rect.height = combo_attr->img_rect.height + ob_height; - } -@@ -400,6 +418,7 @@ static td_void sample_comm_vi_get_mipi_ext_data_attr(sample_sns_type sns_type, e - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT: - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SONY_IMX347_SLAVE_MIPI_4M_30FPS_12BIT: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -@@ -445,6 +464,7 @@ static td_void sample_comm_vi_get_mipi_attr_by_dev_id(sample_sns_type sns_type, - } - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ //ob_height = OB_HEIGHT_END; - if (vi_dev == 0) { - (td_void)memcpy_s(combo_attr, sizeof(combo_dev_attr_t), - &g_mipi_4lane_chn0_sensor_os04a10_12bit_4m_nowdr_attr, sizeof(combo_dev_attr_t)); -@@ -599,6 +619,7 @@ td_void sample_comm_vi_get_size_by_sns_type(sample_sns_type sns_type, ot_size *s - size->height = HEIGHT_2160; - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_2L_MIPI_4M_30FPS_10BIT: -@@ -635,6 +656,7 @@ td_u32 sample_comm_vi_get_obheight_by_sns_type(sample_sns_type sns_type) - ob_height = IMX347_OB_HEIGHT_END; - break; - case OV_OS04A10_MIPI_4M_30FPS_12BIT: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: - case SC450AI_2L_MIPI_4M_30FPS_10BIT: -@@ -663,6 +685,7 @@ static td_u32 sample_comm_vi_get_pipe_num_by_sns_type(sample_sns_type sns_type) - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return 2; /* 2 pipe */ - - default: -@@ -685,6 +708,7 @@ static ot_wdr_mode sample_comm_vi_get_wdr_mode_by_sns_type(sample_sns_type sns_t - case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: - case OV_OS08A20_MIPI_8M_30FPS_12BIT_WDR2TO1: - case SC450AI_MIPI_4M_30FPS_10BIT_WDR2TO1: -+ case OV_OS04A10_MIPI_4M_30FPS_10BIT_WDR2TO1: - return OT_WDR_MODE_2To1_LINE; - - default: -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -index 6d6e27b..b2eb9d8 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.c -@@ -444,7 +444,7 @@ static td_void sample_common_svp_stop_vpss(td_s32 vpss_grp_cnt, td_u32 vpss_chn_ - } - } - --static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) -+td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) - { - ot_rect def_disp_rect = {0, 0, 1920, 1080}; - ot_size def_img_size = {1920, 1080}; -@@ -457,7 +457,7 @@ static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) - vo_cfg->vo_dev = SAMPLE_VO_DEV_UHD; - - vo_cfg->vo_intf_type = OT_VO_INTF_HDMI; -- vo_cfg->intf_sync = OT_VO_OUT_1080P30; -+ vo_cfg->intf_sync = OT_VO_OUT_1080P60; - vo_cfg->bg_color = COLOR_RGB_BLACK; - vo_cfg->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; - vo_cfg->disp_rect = def_disp_rect; -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -index 626a2d6..dd86d96 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp.h -@@ -60,6 +60,8 @@ typedef enum { - - typedef struct { - ot_point point[OT_POINT_NUM]; -+ td_float score; -+ td_u16 class_id; - } ot_sample_svp_rect; - - typedef struct { -diff --git a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -index 3f811f0..469ff32 100644 ---- a/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -+++ b/smp/a55_linux/mpp/sample/svp/common/sample_common_svp_npu_model.c -@@ -999,6 +999,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - td_float *y_min = TD_NULL; - td_float *x_max = TD_NULL; - td_float *y_max = TD_NULL; -+ td_float *score = TD_NULL; -+ td_float *class_id = TD_NULL; - td_u32 roi_offset = info->roi_offset; - td_u32 i; - -@@ -1019,6 +1021,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - y_min = x_min + stride / sizeof(td_float); - x_max = y_min + stride / sizeof(td_float); - y_max = x_max + stride / sizeof(td_float); -+ score = y_max + stride / sizeof(td_float); -+ class_id = score + stride / sizeof(td_float); - - for (i = 0; i < rect_info->num; i++) { - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)((td_float)x_min[roi_offset] / -@@ -1040,6 +1044,8 @@ static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = - rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; -+ rect_info->rect[i].score = (td_float)((td_float)score[roi_offset]); -+ rect_info->rect[i].class_id = (td_u16)((td_float)class_id[roi_offset]); - roi_offset++; - } - return TD_SUCCESS; -@@ -1319,6 +1325,9 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, - const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) - { - td_s32 ret; -+ td_u32 i; -+ td_float max_confidence = 0.0f; -+ td_u32 max_index = 0; - - if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { - sample_svp_trace_err("check task cfg failed!\n"); -@@ -1341,6 +1350,19 @@ td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, - ret = sample_svp_npu_get_roi(task, detection_info, proc_frame, show_frame, rect_info); - sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, - "get roi failed!\n"); -+ if (rect_info->num > 0) { -+ for (i = 0; i < rect_info->num; i++) { -+ if (rect_info->rect[i].score > max_confidence) { -+ max_confidence = rect_info->rect[i].score; -+ max_index = i; -+ } -+ } -+ -+ if (rect_info->num > 1) { -+ rect_info->rect[0] = rect_info->rect[max_index]; -+ rect_info->num = 1; -+ } -+ } - - return TD_SUCCESS; - } --- -2.34.1 - diff --git a/vendor/zsks/patch/gcc/0001-zsks-gcc-linux-6.6.y.patch b/vendor/zsks/patch/gcc/0001-zsks-gcc-linux-6.6.y.patch index 1748052f1a6a2fa67a401eb58ce4c246d1c5c678..2055d1613b2f75c95a0c6a1d544bcc7ad68b4e21 100755 --- a/vendor/zsks/patch/gcc/0001-zsks-gcc-linux-6.6.y.patch +++ b/vendor/zsks/patch/gcc/0001-zsks-gcc-linux-6.6.y.patch @@ -1,21 +1,21 @@ -From cab5069dd66d76cc1411f210683ebf05c6366d32 Mon Sep 17 00:00:00 2001 -From: wgm2022 <1480559020@qq.com> -Date: Mon, 11 May 2026 14:23:46 +0800 -Subject: [PATCH] zsks gcc linux-6.6.y +From 3401872f7411141a6e4046d70d7ddfd85402fb43 Mon Sep 17 00:00:00 2001 +From: wgm <1480559020@qq.com> +Date: Tue, 19 May 2026 16:20:26 +0800 +Subject: [PATCH] zsks-gcc-linux-6.6.y --- - arch/arm64/boot/dts/vendor/ss928v100-demb.dts | 49 +++- - arch/arm64/boot/dts/vendor/ss928v100.dtsi | 38 ++- - arch/arm64/configs/ss928v100_emmc_defconfig | 240 +++++++++++++++++- - drivers/net/ethernet/vendor/gmac/gmac.h | 1 + - .../net/ethernet/vendor/gmac/gmac_phy_fixup.c | 27 ++ - 5 files changed, 339 insertions(+), 16 deletions(-) + arch/arm64/boot/dts/vendor/ss928v100-demb.dts | 49 +- + arch/arm64/boot/dts/vendor/ss928v100.dtsi | 38 +- + arch/arm64/configs/ss928v100_emmc_defconfig | 1295 ++++++++++++++++- + drivers/net/ethernet/vendor/gmac/gmac.h | 1 + + .../net/ethernet/vendor/gmac/gmac_phy_fixup.c | 27 + + 5 files changed, 1367 insertions(+), 43 deletions(-) diff --git a/arch/arm64/boot/dts/vendor/ss928v100-demb.dts b/arch/arm64/boot/dts/vendor/ss928v100-demb.dts index d90c5d5cf..9d291d15f 100644 --- a/arch/arm64/boot/dts/vendor/ss928v100-demb.dts +++ b/arch/arm64/boot/dts/vendor/ss928v100-demb.dts -@@ -125,26 +125,39 @@ +@@ -125,26 +125,39 @@ &uart0 { }; &uart1 { @@ -60,7 +60,7 @@ index d90c5d5cf..9d291d15f 100644 }; &i2c_bus1 { -@@ -167,9 +180,17 @@ +@@ -167,9 +180,17 @@ &i2c_bus5 { status = "okay"; }; @@ -79,7 +79,7 @@ index d90c5d5cf..9d291d15f 100644 spidev@0 { compatible = "rohm,dh2228fv"; reg = <0>; -@@ -177,6 +198,16 @@ +@@ -177,6 +198,16 @@ spidev@0 { pl022,com-mode = <0>; spi-max-frequency = <25000000>; }; @@ -96,7 +96,7 @@ index d90c5d5cf..9d291d15f 100644 }; &spi_bus1{ -@@ -322,9 +353,9 @@ +@@ -322,9 +353,9 @@ ethphy: ethernet-phy@1 { }; &mdio1 { @@ -121,7 +121,7 @@ index 491959516..5c88f8a6f 100644 / { #address-cells = <2>; -@@ -144,6 +145,12 @@ +@@ -144,6 +145,12 @@ clk_3m: clk_3m { clock-frequency = <3000000>; }; @@ -134,7 +134,7 @@ index 491959516..5c88f8a6f 100644 i2c_bus0: i2c@11060000 { compatible = "vendor,i2c"; reg = <0x11060000 0x1000>; -@@ -211,7 +218,29 @@ +@@ -211,7 +218,29 @@ i2c_bus5: i2c@11065000 { /* dmas = <&edmacv310_0 10 10>, <&edmacv310_0 11 11>; */ /* dma-names = "rx","tx"; */ status = "disabled"; @@ -165,7 +165,7 @@ index 491959516..5c88f8a6f 100644 amba { compatible = "arm,amba-bus"; -@@ -428,6 +457,9 @@ +@@ -428,6 +457,9 @@ gpio_chip4: gpio_chip@11094000 { clocks = <&clock SS928V100_FIXED_50M>; clock-names = "apb_pclk"; status = "disabled"; @@ -175,7 +175,7 @@ index 491959516..5c88f8a6f 100644 }; gpio_chip5: gpio_chip@11095000 { -@@ -752,8 +784,8 @@ +@@ -752,8 +784,8 @@ pcie0: pcie@0x103d0000 { 0x0 0x0 0x0 0x3 &gic GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH 0x0 0x0 0x0 0x4 &gic GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; /* msi interrupts */ @@ -187,12 +187,63 @@ index 491959516..5c88f8a6f 100644 pcie_controller = <0>; dev_mem_size = <0x10000000>; diff --git a/arch/arm64/configs/ss928v100_emmc_defconfig b/arch/arm64/configs/ss928v100_emmc_defconfig -index 37f823d7d..e1e395754 100644 +index c4fa70200..c1fb024ff 100644 --- a/arch/arm64/configs/ss928v100_emmc_defconfig +++ b/arch/arm64/configs/ss928v100_emmc_defconfig -@@ -142,7 +142,21 @@ CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +@@ -1,22 +1,24 @@ + # + # Automatically generated file; DO NOT EDIT. +-# Linux/arm64 6.6.90 Kernel Configuration +-# +-CONFIG_CC_VERSION_TEXT="clang version 15.0.4 (v050 musl1.2.3 2023-03-18 10:36:32)" +-CONFIG_GCC_VERSION=0 +-CONFIG_CC_IS_CLANG=y +-CONFIG_CLANG_VERSION=150004 +-CONFIG_AS_IS_LLVM=y +-CONFIG_AS_VERSION=150004 +-CONFIG_LD_VERSION=0 +-CONFIG_LD_IS_LLD=y +-CONFIG_LLD_VERSION=150004 ++# Linux/arm64 6.6.86 Kernel Configuration ++# ++CONFIG_CC_VERSION_TEXT="aarch64-openeuler-linux-gnu-gcc (crosstool-NG 1.26.0) 12.3.1 20230508" ++CONFIG_CC_IS_GCC=y ++CONFIG_GCC_VERSION=120301 ++CONFIG_CLANG_VERSION=0 ++CONFIG_AS_IS_GNU=y ++CONFIG_AS_VERSION=24100 ++CONFIG_LD_IS_BFD=y ++CONFIG_LD_VERSION=24100 ++CONFIG_LLD_VERSION=0 ++CONFIG_CC_CAN_LINK=y ++CONFIG_CC_CAN_LINK_STATIC=y + CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y + CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y +-CONFIG_TOOLS_SUPPORT_RELR=y ++CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y + CONFIG_CC_HAS_ASM_INLINE=y + CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +-CONFIG_PAHOLE_VERSION=121 ++CONFIG_PAHOLE_VERSION=0 + CONFIG_IRQ_WORK=y + CONFIG_BUILDTIME_TABLE_SORT=y + CONFIG_THREAD_INFO_IN_TASK=y +@@ -54,6 +56,7 @@ CONFIG_IRQ_DOMAIN=y + CONFIG_IRQ_DOMAIN_HIERARCHY=y + CONFIG_GENERIC_IRQ_IPI=y + CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_IRQ_MSI_IOMMU=y + CONFIG_IRQ_FORCED_THREADING=y + CONFIG_SPARSE_IRQ=y + # end of IRQ subsystem +@@ -135,10 +138,25 @@ CONFIG_GENERIC_SCHED_CLOCK=y + CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y + CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y + CONFIG_CC_HAS_INT128=y +-CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough" ++CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" CONFIG_GCC10_NO_ARRAY_BOUNDS=y - CONFIG_CC_NO_ARRAY_BOUNDS=y ++CONFIG_CC_NO_ARRAY_BOUNDS=y CONFIG_ARCH_SUPPORTS_INT128=y -# CONFIG_CGROUPS is not set +CONFIG_CGROUPS=y @@ -213,7 +264,76 @@ index 37f823d7d..e1e395754 100644 CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_TIME_NS=y -@@ -996,6 +1010,8 @@ CONFIG_RPS=y +@@ -208,7 +226,7 @@ CONFIG_HAVE_PERF_EVENTS=y + # end of General setup + + CONFIG_ARM64=y +-CONFIG_CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y ++CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y + CONFIG_64BIT=y + CONFIG_MMU=y + CONFIG_ARM64_PAGE_SHIFT=12 +@@ -253,6 +271,7 @@ CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y + # CONFIG_ARCH_KEEMBAY is not set + CONFIG_ARCH_BSP=y + CONFIG_ARCH_SS928V100=y ++# CONFIG_ARCH_SS927V100 is not set + # CONFIG_ARCH_MEDIATEK is not set + # CONFIG_ARCH_MESON is not set + # CONFIG_ARCH_MVEBU is not set +@@ -417,7 +436,6 @@ CONFIG_ARM64_TLB_RANGE=y + # + CONFIG_AS_HAS_ARMV8_5=y + CONFIG_ARM64_BTI=y +-CONFIG_ARM64_BTI_KERNEL=y + CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y + CONFIG_ARM64_E0PD=y + CONFIG_ARM64_AS_HAS_MTE=y +@@ -557,10 +575,7 @@ CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y + # CONFIG_SHADOW_CALL_STACK is not set + CONFIG_ARCH_SUPPORTS_LTO_CLANG=y + CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y +-CONFIG_HAS_LTO_CLANG=y + CONFIG_LTO_NONE=y +-# CONFIG_LTO_CLANG_FULL is not set +-# CONFIG_LTO_CLANG_THIN is not set + CONFIG_ARCH_SUPPORTS_CFI_CLANG=y + CONFIG_HAVE_CONTEXT_TRACKING_USER=y + CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +@@ -595,7 +610,6 @@ CONFIG_STRICT_MODULE_RWX=y + CONFIG_HAVE_ARCH_COMPILER_H=y + CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y + CONFIG_ARCH_HAS_RELR=y +-CONFIG_RELR=y + CONFIG_HAVE_PREEMPT_DYNAMIC=y + CONFIG_HAVE_PREEMPT_DYNAMIC_KEY=y + CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y +@@ -610,6 +624,8 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y + # end of GCOV-based kernel profiling + + CONFIG_HAVE_GCC_PLUGINS=y ++CONFIG_GCC_PLUGINS=y ++# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set + CONFIG_FUNCTION_ALIGNMENT_4B=y + CONFIG_FUNCTION_ALIGNMENT=4 + # end of General architecture-dependent options +@@ -795,6 +811,7 @@ CONFIG_MIGRATION=y + CONFIG_CONTIG_ALLOC=y + CONFIG_PCP_BATCH_SCALE_MAX=5 + CONFIG_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU_NOTIFIER=y + CONFIG_KSM=y + CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 + CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +@@ -859,6 +876,7 @@ CONFIG_AF_UNIX_OOB=y + # CONFIG_XFRM_USER is not set + # CONFIG_NET_KEY is not set + # CONFIG_XDP_SOCKETS is not set ++CONFIG_NET_HANDSHAKE=y + CONFIG_INET=y + CONFIG_IP_MULTICAST=y + # CONFIG_IP_ADVANCED_ROUTER is not set +@@ -992,6 +1010,8 @@ CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_SOCK_RX_QUEUE_MAPPING=y CONFIG_XPS=y @@ -222,7 +342,7 @@ index 37f823d7d..e1e395754 100644 CONFIG_NET_RX_BUSY_POLL=y CONFIG_BQL=y CONFIG_NET_FLOW_LIMIT=y -@@ -1008,7 +1024,12 @@ CONFIG_NET_FLOW_LIMIT=y +@@ -1004,7 +1024,12 @@ CONFIG_NET_FLOW_LIMIT=y # end of Networking options # CONFIG_HAMRADIO is not set @@ -236,7 +356,71 @@ index 37f823d7d..e1e395754 100644 # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set # CONFIG_AF_KCM is not set -@@ -1391,6 +1412,48 @@ CONFIG_REALTEK_PHY=y +@@ -1071,7 +1096,11 @@ CONFIG_GENERIC_CPU_AUTOPROBE=y + CONFIG_GENERIC_CPU_VULNERABILITIES=y + CONFIG_SOC_BUS=y + CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y + CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_DMA_FENCE_TRACE is not set + CONFIG_GENERIC_ARCH_TOPOLOGY=y + # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set + # end of Generic Driver Options +@@ -1131,9 +1160,18 @@ CONFIG_OF_RESERVED_MEM=y + # CONFIG_OF_OVERLAY is not set + # CONFIG_PARPORT is not set + CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_ZRAM is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set + CONFIG_BLK_DEV_RAM=y + CONFIG_BLK_DEV_RAM_COUNT=16 + CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_UBLK is not set + + # + # NVME Support +@@ -1161,6 +1199,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 + # CONFIG_LATTICE_ECP3_CONFIG is not set + # CONFIG_SRAM is not set + # CONFIG_XILINX_SDFEC is not set ++# CONFIG_HISI_HIKEY_USB is not set + # CONFIG_OPEN_DICE is not set + # CONFIG_VCPU_STALL_DETECTOR is not set + # CONFIG_C2PORT is not set +@@ -1189,6 +1228,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 + # CONFIG_ALTERA_STAPL is not set + # CONFIG_ECHO is not set + # CONFIG_MISC_RTSX_USB is not set ++# CONFIG_UACCE is not set + # CONFIG_PVPANIC is not set + # end of Misc devices + +@@ -1207,6 +1247,7 @@ CONFIG_SCSI_PROC_FS=y + # + CONFIG_BLK_DEV_SD=y + # CONFIG_CHR_DEV_ST is not set ++# CONFIG_BLK_DEV_SR is not set + # CONFIG_CHR_DEV_SG is not set + CONFIG_BLK_DEV_BSG=y + # CONFIG_CHR_DEV_SCH is not set +@@ -1355,7 +1396,7 @@ CONFIG_FIXED_PHY=y + # CONFIG_NXP_C45_TJA11XX_PHY is not set + # CONFIG_NCN26000_PHY is not set + # CONFIG_QSEMI_PHY is not set +-# CONFIG_REALTEK_PHY is not set ++CONFIG_REALTEK_PHY=y + # CONFIG_RENESAS_PHY is not set + # CONFIG_ROCKCHIP_PHY is not set + # CONFIG_SMSC_PHY is not set +@@ -1372,6 +1413,48 @@ CONFIG_FIXED_PHY=y CONFIG_MDIO_BSP_GEMAC=y # CONFIG_MICREL_KS8995MA is not set # CONFIG_PSE_CONTROLLER is not set @@ -285,11 +469,946 @@ index 37f823d7d..e1e395754 100644 CONFIG_MDIO_DEVICE=y CONFIG_MDIO_BUS=y CONFIG_FWNODE_MDIO=y -@@ -2740,7 +2803,123 @@ CONFIG_SND_USB=y - # CONFIG_SND_USB_TONEPORT is not set - # CONFIG_SND_USB_VARIAX is not set - # CONFIG_SND_SOC is not set +@@ -1977,10 +2060,659 @@ CONFIG_MFD_SYSCON=y + # end of CEC support + + CONFIG_MEDIA_SUPPORT=y ++# CONFIG_MEDIA_SUPPORT_FILTER is not set ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++ ++# ++# Media device types ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_SDR_SUPPORT=y ++CONFIG_MEDIA_PLATFORM_SUPPORT=y ++CONFIG_MEDIA_TEST_SUPPORT=y ++# end of Media device types ++ ++# ++# Media core support ++# ++CONFIG_VIDEO_DEV=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_DVB_CORE=y ++# end of Media core support ++ ++# ++# Video4Linux options ++# ++CONFIG_VIDEO_V4L2_I2C=y ++CONFIG_VIDEO_V4L2_SUBDEV_API=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_V4L2_FWNODE=y ++CONFIG_V4L2_ASYNC=y ++# end of Video4Linux options ++ ++# ++# Media controller options ++# ++# CONFIG_MEDIA_CONTROLLER_DVB is not set ++# end of Media controller options ++ ++# ++# Digital TV options ++# ++# CONFIG_DVB_MMAP is not set ++CONFIG_DVB_NET=y ++CONFIG_DVB_MAX_ADAPTERS=16 ++CONFIG_DVB_DYNAMIC_MINORS=y ++# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set ++# CONFIG_DVB_ULE_DEBUG is not set ++# end of Digital TV options ++ ++# ++# Media drivers ++# ++ ++# ++# Media drivers ++# + CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++# CONFIG_USB_GSPCA is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_USB_S2255 is not set ++# CONFIG_VIDEO_USBTV is not set + CONFIG_USB_VIDEO_CLASS=y + CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y + ++# ++# Analog TV USB devices ++# ++# CONFIG_VIDEO_GO7007 is not set ++# CONFIG_VIDEO_HDPVR is not set ++# CONFIG_VIDEO_PVRUSB2 is not set ++# CONFIG_VIDEO_STK1160 is not set ++ ++# ++# Analog/digital TV USB devices ++# ++# CONFIG_VIDEO_AU0828 is not set ++# CONFIG_VIDEO_CX231XX is not set ++ ++# ++# Digital TV USB devices ++# ++# CONFIG_DVB_AS102 is not set ++# CONFIG_DVB_B2C2_FLEXCOP_USB is not set ++# CONFIG_DVB_USB_V2 is not set ++# CONFIG_SMS_USB_DRV is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++ ++# ++# Software defined radio USB devices ++# ++# CONFIG_USB_AIRSPY is not set ++# CONFIG_USB_HACKRF is not set ++# CONFIG_USB_MSI2500 is not set ++CONFIG_RADIO_ADAPTERS=y ++# CONFIG_RADIO_SAA7706H is not set ++# CONFIG_RADIO_SHARK is not set ++# CONFIG_RADIO_SHARK2 is not set ++# CONFIG_RADIO_SI4713 is not set ++# CONFIG_RADIO_TEA5764 is not set ++# CONFIG_RADIO_TEF6862 is not set ++# CONFIG_RADIO_WL1273 is not set ++# CONFIG_USB_DSBR is not set ++# CONFIG_USB_KEENE is not set ++# CONFIG_USB_MA901 is not set ++# CONFIG_USB_MR800 is not set ++# CONFIG_USB_RAREMONO is not set ++# CONFIG_RADIO_SI470X is not set ++CONFIG_MEDIA_PLATFORM_DRIVERS=y ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_SDR_PLATFORM_DRIVERS is not set ++# CONFIG_DVB_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++ ++# ++# Allegro DVT media platform drivers ++# ++ ++# ++# Amlogic media platform drivers ++# ++ ++# ++# Amphion drivers ++# ++ ++# ++# Aspeed media platform drivers ++# ++ ++# ++# Atmel media platform drivers ++# ++ ++# ++# Cadence media platform drivers ++# ++# CONFIG_VIDEO_CADENCE_CSI2RX is not set ++# CONFIG_VIDEO_CADENCE_CSI2TX is not set ++ ++# ++# Chips&Media media platform drivers ++# ++ ++# ++# Intel media platform drivers ++# ++ ++# ++# Marvell media platform drivers ++# ++ ++# ++# Mediatek media platform drivers ++# ++ ++# ++# Microchip Technology, Inc. media platform drivers ++# ++ ++# ++# NVidia media platform drivers ++# ++ ++# ++# NXP media platform drivers ++# ++ ++# ++# Qualcomm media platform drivers ++# ++ ++# ++# Renesas media platform drivers ++# ++ ++# ++# Rockchip media platform drivers ++# ++ ++# ++# Samsung media platform drivers ++# ++ ++# ++# STMicroelectronics media platform drivers ++# ++ ++# ++# Sunxi media platform drivers ++# ++ ++# ++# Texas Instruments drivers ++# ++ ++# ++# Verisilicon media platform drivers ++# ++ ++# ++# VIA media platform drivers ++# ++ ++# ++# Xilinx media platform drivers ++# ++ ++# ++# MMC/SDIO DVB adapters ++# ++# CONFIG_SMS_SDIO_DRV is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++# CONFIG_DVB_TEST_DRIVERS is not set ++CONFIG_UVC_COMMON=y ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_V4L2=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++CONFIG_VIDEOBUF2_DMA_SG=y ++# end of Media drivers ++ ++# ++# Media ancillary drivers ++# ++CONFIG_MEDIA_ATTACH=y ++CONFIG_VIDEO_CAMERA_SENSOR=y ++# CONFIG_VIDEO_AR0521 is not set ++# CONFIG_VIDEO_HI556 is not set ++# CONFIG_VIDEO_HI846 is not set ++# CONFIG_VIDEO_HI847 is not set ++# CONFIG_VIDEO_IMX208 is not set ++# CONFIG_VIDEO_IMX214 is not set ++# CONFIG_VIDEO_IMX219 is not set ++# CONFIG_VIDEO_IMX258 is not set ++# CONFIG_VIDEO_IMX274 is not set ++# CONFIG_VIDEO_IMX290 is not set ++# CONFIG_VIDEO_IMX296 is not set ++# CONFIG_VIDEO_IMX319 is not set ++# CONFIG_VIDEO_IMX334 is not set ++# CONFIG_VIDEO_IMX335 is not set ++# CONFIG_VIDEO_IMX355 is not set ++# CONFIG_VIDEO_IMX412 is not set ++# CONFIG_VIDEO_IMX415 is not set ++# CONFIG_VIDEO_MT9M001 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9P031 is not set ++# CONFIG_VIDEO_MT9T112 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_MT9V032 is not set ++# CONFIG_VIDEO_MT9V111 is not set ++# CONFIG_VIDEO_OG01A1B is not set ++# CONFIG_VIDEO_OV01A10 is not set ++# CONFIG_VIDEO_OV02A10 is not set ++# CONFIG_VIDEO_OV08D10 is not set ++# CONFIG_VIDEO_OV08X40 is not set ++# CONFIG_VIDEO_OV13858 is not set ++# CONFIG_VIDEO_OV13B10 is not set ++# CONFIG_VIDEO_OV2640 is not set ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV2680 is not set ++# CONFIG_VIDEO_OV2685 is not set ++# CONFIG_VIDEO_OV4689 is not set ++# CONFIG_VIDEO_OV5640 is not set ++# CONFIG_VIDEO_OV5645 is not set ++# CONFIG_VIDEO_OV5647 is not set ++# CONFIG_VIDEO_OV5648 is not set ++# CONFIG_VIDEO_OV5670 is not set ++# CONFIG_VIDEO_OV5675 is not set ++# CONFIG_VIDEO_OV5693 is not set ++# CONFIG_VIDEO_OV5695 is not set ++# CONFIG_VIDEO_OV6650 is not set ++# CONFIG_VIDEO_OV7251 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_OV772X is not set ++# CONFIG_VIDEO_OV7740 is not set ++# CONFIG_VIDEO_OV8856 is not set ++# CONFIG_VIDEO_OV8858 is not set ++# CONFIG_VIDEO_OV8865 is not set ++# CONFIG_VIDEO_OV9282 is not set ++# CONFIG_VIDEO_OV9640 is not set ++# CONFIG_VIDEO_OV9650 is not set ++# CONFIG_VIDEO_RDACM20 is not set ++# CONFIG_VIDEO_RDACM21 is not set ++# CONFIG_VIDEO_RJ54N1 is not set ++# CONFIG_VIDEO_S5C73M3 is not set ++# CONFIG_VIDEO_S5K5BAF is not set ++# CONFIG_VIDEO_S5K6A3 is not set ++# CONFIG_VIDEO_ST_VGXY61 is not set ++# CONFIG_VIDEO_CCS is not set ++# CONFIG_VIDEO_ET8EK8 is not set ++ ++# ++# Lens drivers ++# ++# CONFIG_VIDEO_AD5820 is not set ++# CONFIG_VIDEO_AK7375 is not set ++# CONFIG_VIDEO_DW9714 is not set ++# CONFIG_VIDEO_DW9719 is not set ++# CONFIG_VIDEO_DW9768 is not set ++# CONFIG_VIDEO_DW9807_VCM is not set ++# end of Lens drivers ++ ++# ++# Flash devices ++# ++# CONFIG_VIDEO_ADP1653 is not set ++# CONFIG_VIDEO_LM3560 is not set ++# CONFIG_VIDEO_LM3646 is not set ++# end of Flash devices ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++# CONFIG_VIDEO_TDA1997X is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# end of Audio decoders, processors and mixers ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++# end of RDS decoders ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7180 is not set ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_ADV748X is not set ++# CONFIG_VIDEO_ADV7604 is not set ++# CONFIG_VIDEO_ADV7842 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_ISL7998X is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_MAX9286 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TC358743 is not set ++# CONFIG_VIDEO_TC358746 is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_TW9910 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++# end of Video decoders ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_ADV7511 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_THS8200 is not set ++# end of Video encoders ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++# end of Video improvement chips ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++# end of Audio/Video compression chips ++ ++# ++# SDR tuner chips ++# ++# CONFIG_SDR_MAX2175 is not set ++# end of SDR tuner chips ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_I2C is not set ++# CONFIG_VIDEO_M52790 is not set ++# CONFIG_VIDEO_ST_MIPID02 is not set ++# CONFIG_VIDEO_THS7303 is not set ++# end of Miscellaneous helper chips ++ ++# ++# Video serializers and deserializers ++# ++# CONFIG_VIDEO_DS90UB913 is not set ++# CONFIG_VIDEO_DS90UB953 is not set ++# CONFIG_VIDEO_DS90UB960 is not set ++# end of Video serializers and deserializers ++ ++# ++# Media SPI Adapters ++# ++CONFIG_CXD2880_SPI_DRV=m ++# CONFIG_VIDEO_GS1662 is not set ++# end of Media SPI Adapters ++ ++CONFIG_MEDIA_TUNER=y ++ ++# ++# Customize TV tuners ++# ++CONFIG_MEDIA_TUNER_E4000=m ++CONFIG_MEDIA_TUNER_FC0011=m ++CONFIG_MEDIA_TUNER_FC0012=m ++CONFIG_MEDIA_TUNER_FC0013=m ++CONFIG_MEDIA_TUNER_FC2580=m ++CONFIG_MEDIA_TUNER_IT913X=m ++CONFIG_MEDIA_TUNER_M88RS6000T=m ++CONFIG_MEDIA_TUNER_MAX2165=m ++CONFIG_MEDIA_TUNER_MC44S803=m ++CONFIG_MEDIA_TUNER_MSI001=m ++CONFIG_MEDIA_TUNER_MT2060=m ++CONFIG_MEDIA_TUNER_MT2063=m ++CONFIG_MEDIA_TUNER_MT20XX=m ++CONFIG_MEDIA_TUNER_MT2131=m ++CONFIG_MEDIA_TUNER_MT2266=m ++CONFIG_MEDIA_TUNER_MXL301RF=m ++CONFIG_MEDIA_TUNER_MXL5005S=m ++CONFIG_MEDIA_TUNER_MXL5007T=m ++CONFIG_MEDIA_TUNER_QM1D1B0004=m ++CONFIG_MEDIA_TUNER_QM1D1C0042=m ++CONFIG_MEDIA_TUNER_QT1010=m ++CONFIG_MEDIA_TUNER_R820T=m ++CONFIG_MEDIA_TUNER_SI2157=m ++CONFIG_MEDIA_TUNER_SIMPLE=m ++CONFIG_MEDIA_TUNER_TDA18212=m ++CONFIG_MEDIA_TUNER_TDA18218=m ++CONFIG_MEDIA_TUNER_TDA18250=m ++CONFIG_MEDIA_TUNER_TDA18271=m ++CONFIG_MEDIA_TUNER_TDA827X=m ++CONFIG_MEDIA_TUNER_TDA8290=m ++CONFIG_MEDIA_TUNER_TDA9887=m ++CONFIG_MEDIA_TUNER_TEA5761=m ++CONFIG_MEDIA_TUNER_TEA5767=m ++CONFIG_MEDIA_TUNER_TUA9001=m ++CONFIG_MEDIA_TUNER_XC2028=m ++CONFIG_MEDIA_TUNER_XC4000=m ++CONFIG_MEDIA_TUNER_XC5000=m ++# end of Customize TV tuners ++ ++# ++# Customise DVB Frontends ++# ++ ++# ++# Multistandard (satellite) frontends ++# ++CONFIG_DVB_M88DS3103=m ++CONFIG_DVB_MXL5XX=m ++CONFIG_DVB_STB0899=m ++CONFIG_DVB_STB6100=m ++CONFIG_DVB_STV090x=m ++CONFIG_DVB_STV0910=m ++CONFIG_DVB_STV6110x=m ++CONFIG_DVB_STV6111=m ++ ++# ++# Multistandard (cable + terrestrial) frontends ++# ++CONFIG_DVB_DRXK=m ++CONFIG_DVB_MN88472=m ++CONFIG_DVB_MN88473=m ++CONFIG_DVB_SI2165=m ++CONFIG_DVB_TDA18271C2DD=m ++ ++# ++# DVB-S (satellite) frontends ++# ++CONFIG_DVB_CX24110=m ++CONFIG_DVB_CX24116=m ++CONFIG_DVB_CX24117=m ++CONFIG_DVB_CX24120=m ++CONFIG_DVB_CX24123=m ++CONFIG_DVB_DS3000=m ++CONFIG_DVB_MB86A16=m ++CONFIG_DVB_MT312=m ++CONFIG_DVB_S5H1420=m ++CONFIG_DVB_SI21XX=m ++CONFIG_DVB_STB6000=m ++CONFIG_DVB_STV0288=m ++CONFIG_DVB_STV0299=m ++CONFIG_DVB_STV0900=m ++CONFIG_DVB_STV6110=m ++CONFIG_DVB_TDA10071=m ++CONFIG_DVB_TDA10086=m ++CONFIG_DVB_TDA8083=m ++CONFIG_DVB_TDA8261=m ++CONFIG_DVB_TDA826X=m ++CONFIG_DVB_TS2020=m ++CONFIG_DVB_TUA6100=m ++CONFIG_DVB_TUNER_CX24113=m ++CONFIG_DVB_TUNER_ITD1000=m ++CONFIG_DVB_VES1X93=m ++CONFIG_DVB_ZL10036=m ++CONFIG_DVB_ZL10039=m ++ ++# ++# DVB-T (terrestrial) frontends ++# ++CONFIG_DVB_AF9013=m ++CONFIG_DVB_CX22700=m ++CONFIG_DVB_CX22702=m ++CONFIG_DVB_CXD2820R=m ++CONFIG_DVB_CXD2841ER=m ++CONFIG_DVB_DIB3000MB=m ++CONFIG_DVB_DIB3000MC=m ++CONFIG_DVB_DIB7000M=m ++CONFIG_DVB_DIB7000P=m ++CONFIG_DVB_DIB9000=m ++CONFIG_DVB_DRXD=m ++CONFIG_DVB_EC100=m ++CONFIG_DVB_L64781=m ++CONFIG_DVB_MT352=m ++CONFIG_DVB_NXT6000=m ++CONFIG_DVB_RTL2830=m ++CONFIG_DVB_RTL2832=m ++CONFIG_DVB_RTL2832_SDR=m ++CONFIG_DVB_S5H1432=m ++CONFIG_DVB_SI2168=m ++CONFIG_DVB_SP887X=m ++CONFIG_DVB_STV0367=m ++CONFIG_DVB_TDA10048=m ++CONFIG_DVB_TDA1004X=m ++CONFIG_DVB_ZD1301_DEMOD=m ++CONFIG_DVB_ZL10353=m ++CONFIG_DVB_CXD2880=m ++ ++# ++# DVB-C (cable) frontends ++# ++CONFIG_DVB_STV0297=m ++CONFIG_DVB_TDA10021=m ++CONFIG_DVB_TDA10023=m ++CONFIG_DVB_VES1820=m ++ ++# ++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends ++# ++CONFIG_DVB_AU8522=m ++CONFIG_DVB_AU8522_DTV=m ++CONFIG_DVB_AU8522_V4L=m ++CONFIG_DVB_BCM3510=m ++CONFIG_DVB_LG2160=m ++CONFIG_DVB_LGDT3305=m ++CONFIG_DVB_LGDT3306A=m ++CONFIG_DVB_LGDT330X=m ++CONFIG_DVB_MXL692=m ++CONFIG_DVB_NXT200X=m ++CONFIG_DVB_OR51132=m ++CONFIG_DVB_OR51211=m ++CONFIG_DVB_S5H1409=m ++CONFIG_DVB_S5H1411=m ++ ++# ++# ISDB-T (terrestrial) frontends ++# ++CONFIG_DVB_DIB8000=m ++CONFIG_DVB_MB86A20S=m ++CONFIG_DVB_S921=m ++ ++# ++# ISDB-S (satellite) & ISDB-T (terrestrial) frontends ++# ++CONFIG_DVB_MN88443X=m ++CONFIG_DVB_TC90522=m ++ ++# ++# Digital terrestrial only tuners/PLL ++# ++CONFIG_DVB_PLL=m ++CONFIG_DVB_TUNER_DIB0070=m ++CONFIG_DVB_TUNER_DIB0090=m ++ ++# ++# SEC control devices for DVB-S ++# ++CONFIG_DVB_A8293=m ++CONFIG_DVB_AF9033=m ++CONFIG_DVB_ASCOT2E=m ++CONFIG_DVB_ATBM8830=m ++CONFIG_DVB_HELENE=m ++CONFIG_DVB_HORUS3A=m ++CONFIG_DVB_ISL6405=m ++CONFIG_DVB_ISL6421=m ++CONFIG_DVB_ISL6423=m ++CONFIG_DVB_IX2505V=m ++CONFIG_DVB_LGS8GL5=m ++CONFIG_DVB_LGS8GXX=m ++CONFIG_DVB_LNBH25=m ++CONFIG_DVB_LNBH29=m ++CONFIG_DVB_LNBP21=m ++CONFIG_DVB_LNBP22=m ++CONFIG_DVB_M88RS2000=m ++CONFIG_DVB_TDA665x=m ++CONFIG_DVB_DRX39XYJ=m ++ ++# ++# Common Interface (EN50221) controller drivers ++# ++CONFIG_DVB_CXD2099=m ++CONFIG_DVB_SP2=m ++# end of Customise DVB Frontends ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++# end of Media ancillary drivers ++ + # + # Graphics support + # +@@ -2034,8 +2766,398 @@ CONFIG_DUMMY_CONSOLE_ROWS=25 + + CONFIG_SOUND=y + CONFIG_SND=y ++CONFIG_SND_TIMER=y ++CONFIG_SND_PCM=y ++CONFIG_SND_JACK=y ++CONFIG_SND_JACK_INPUT_DEV=y ++# CONFIG_SND_OSSEMUL is not set ++CONFIG_SND_PCM_TIMER=y ++# CONFIG_SND_DYNAMIC_MINORS is not set ++CONFIG_SND_SUPPORT_OLD_API=y ++CONFIG_SND_PROC_FS=y ++CONFIG_SND_VERBOSE_PROCFS=y ++# CONFIG_SND_VERBOSE_PRINTK is not set ++CONFIG_SND_CTL_FAST_LOOKUP=y ++# CONFIG_SND_DEBUG is not set ++# CONFIG_SND_CTL_INPUT_VALIDATION is not set ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_DRIVERS=y ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_ALOOP is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++# ++# HD-Audio ++# ++# end of HD-Audio ++ ++CONFIG_SND_HDA_PREALLOC_SIZE=64 ++CONFIG_SND_SPI=y + CONFIG_SND_USB=y -# CONFIG_HID_SUPPORT is not set ++# CONFIG_SND_USB_AUDIO is not set ++# CONFIG_SND_USB_UA101 is not set ++# CONFIG_SND_USB_CAIAQ is not set ++# CONFIG_SND_USB_6FIRE is not set ++# CONFIG_SND_USB_HIFACE is not set ++# CONFIG_SND_BCD2000 is not set ++# CONFIG_SND_USB_POD is not set ++# CONFIG_SND_USB_PODHD is not set ++# CONFIG_SND_USB_TONEPORT is not set ++# CONFIG_SND_USB_VARIAX is not set ++CONFIG_SND_SOC=y ++# CONFIG_SND_SOC_ADI is not set ++# CONFIG_SND_SOC_AMD_ACP is not set ++# CONFIG_SND_AMD_ACP_CONFIG is not set ++# CONFIG_SND_ATMEL_SOC is not set ++# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set ++# CONFIG_SND_DESIGNWARE_I2S is not set ++ ++# ++# SoC Audio for Freescale CPUs ++# ++ ++# ++# Common SoC Audio options for Freescale CPUs: ++# ++# CONFIG_SND_SOC_FSL_ASRC is not set ++# CONFIG_SND_SOC_FSL_SAI is not set ++# CONFIG_SND_SOC_FSL_AUDMIX is not set ++# CONFIG_SND_SOC_FSL_SSI is not set ++# CONFIG_SND_SOC_FSL_SPDIF is not set ++# CONFIG_SND_SOC_FSL_ESAI is not set ++# CONFIG_SND_SOC_FSL_MICFIL is not set ++# CONFIG_SND_SOC_FSL_XCVR is not set ++# CONFIG_SND_SOC_IMX_AUDMUX is not set ++# end of SoC Audio for Freescale CPUs ++ ++# CONFIG_SND_SOC_CHV3_I2S is not set ++# CONFIG_SND_I2S_HI6210_I2S is not set ++# CONFIG_SND_SOC_IMG is not set ++# CONFIG_SND_SOC_MTK_BTCVSD is not set ++# CONFIG_SND_SOC_SOF_TOPLEVEL is not set ++ ++# ++# STMicroelectronics STM32 SOC audio support ++# ++# end of STMicroelectronics STM32 SOC audio support ++ ++# CONFIG_SND_SOC_XILINX_I2S is not set ++# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set ++# CONFIG_SND_SOC_XILINX_SPDIF is not set ++# CONFIG_SND_SOC_XTFPGA_I2S is not set ++CONFIG_SND_SOC_I2C_AND_SPI=y ++ ++# ++# CODEC drivers ++# ++# CONFIG_SND_SOC_AC97_CODEC is not set ++# CONFIG_SND_SOC_ADAU1372_I2C is not set ++# CONFIG_SND_SOC_ADAU1372_SPI is not set ++# CONFIG_SND_SOC_ADAU1701 is not set ++# CONFIG_SND_SOC_ADAU1761_I2C is not set ++# CONFIG_SND_SOC_ADAU1761_SPI is not set ++# CONFIG_SND_SOC_ADAU7002 is not set ++# CONFIG_SND_SOC_ADAU7118_HW is not set ++# CONFIG_SND_SOC_ADAU7118_I2C is not set ++# CONFIG_SND_SOC_AK4104 is not set ++# CONFIG_SND_SOC_AK4118 is not set ++# CONFIG_SND_SOC_AK4375 is not set ++# CONFIG_SND_SOC_AK4458 is not set ++# CONFIG_SND_SOC_AK4554 is not set ++# CONFIG_SND_SOC_AK4613 is not set ++# CONFIG_SND_SOC_AK4642 is not set ++# CONFIG_SND_SOC_AK5386 is not set ++# CONFIG_SND_SOC_AK5558 is not set ++# CONFIG_SND_SOC_ALC5623 is not set ++# CONFIG_SND_SOC_AW8738 is not set ++# CONFIG_SND_SOC_AW88395 is not set ++# CONFIG_SND_SOC_AW88261 is not set ++# CONFIG_SND_SOC_BD28623 is not set ++# CONFIG_SND_SOC_BT_SCO is not set ++# CONFIG_SND_SOC_CHV3_CODEC is not set ++# CONFIG_SND_SOC_CS35L32 is not set ++# CONFIG_SND_SOC_CS35L33 is not set ++# CONFIG_SND_SOC_CS35L34 is not set ++# CONFIG_SND_SOC_CS35L35 is not set ++# CONFIG_SND_SOC_CS35L36 is not set ++# CONFIG_SND_SOC_CS35L41_SPI is not set ++# CONFIG_SND_SOC_CS35L41_I2C is not set ++# CONFIG_SND_SOC_CS35L45_SPI is not set ++# CONFIG_SND_SOC_CS35L45_I2C is not set ++# CONFIG_SND_SOC_CS35L56_I2C is not set ++# CONFIG_SND_SOC_CS35L56_SPI is not set ++# CONFIG_SND_SOC_CS42L42 is not set ++# CONFIG_SND_SOC_CS42L51_I2C is not set ++# CONFIG_SND_SOC_CS42L52 is not set ++# CONFIG_SND_SOC_CS42L56 is not set ++# CONFIG_SND_SOC_CS42L73 is not set ++# CONFIG_SND_SOC_CS42L83 is not set ++# CONFIG_SND_SOC_CS4234 is not set ++# CONFIG_SND_SOC_CS4265 is not set ++# CONFIG_SND_SOC_CS4270 is not set ++# CONFIG_SND_SOC_CS4271_I2C is not set ++# CONFIG_SND_SOC_CS4271_SPI is not set ++# CONFIG_SND_SOC_CS42XX8_I2C is not set ++# CONFIG_SND_SOC_CS43130 is not set ++# CONFIG_SND_SOC_CS4341 is not set ++# CONFIG_SND_SOC_CS4349 is not set ++# CONFIG_SND_SOC_CS53L30 is not set ++# CONFIG_SND_SOC_CX2072X is not set ++# CONFIG_SND_SOC_DA7213 is not set ++# CONFIG_SND_SOC_DMIC is not set ++# CONFIG_SND_SOC_ES7134 is not set ++# CONFIG_SND_SOC_ES7241 is not set ++# CONFIG_SND_SOC_ES8316 is not set ++# CONFIG_SND_SOC_ES8326 is not set ++# CONFIG_SND_SOC_ES8328_I2C is not set ++# CONFIG_SND_SOC_ES8328_SPI is not set ++# CONFIG_SND_SOC_GTM601 is not set ++# CONFIG_SND_SOC_HDA is not set ++# CONFIG_SND_SOC_ICS43432 is not set ++# CONFIG_SND_SOC_IDT821034 is not set ++# CONFIG_SND_SOC_INNO_RK3036 is not set ++# CONFIG_SND_SOC_MAX98088 is not set ++# CONFIG_SND_SOC_MAX98090 is not set ++# CONFIG_SND_SOC_MAX98357A is not set ++# CONFIG_SND_SOC_MAX98504 is not set ++# CONFIG_SND_SOC_MAX9867 is not set ++# CONFIG_SND_SOC_MAX98927 is not set ++# CONFIG_SND_SOC_MAX98520 is not set ++# CONFIG_SND_SOC_MAX98373_I2C is not set ++# CONFIG_SND_SOC_MAX98388 is not set ++# CONFIG_SND_SOC_MAX98390 is not set ++# CONFIG_SND_SOC_MAX98396 is not set ++# CONFIG_SND_SOC_MAX9860 is not set ++# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set ++# CONFIG_SND_SOC_PCM1681 is not set ++# CONFIG_SND_SOC_PCM1789_I2C is not set ++# CONFIG_SND_SOC_PCM179X_I2C is not set ++# CONFIG_SND_SOC_PCM179X_SPI is not set ++# CONFIG_SND_SOC_PCM186X_I2C is not set ++# CONFIG_SND_SOC_PCM186X_SPI is not set ++# CONFIG_SND_SOC_PCM3060_I2C is not set ++# CONFIG_SND_SOC_PCM3060_SPI is not set ++# CONFIG_SND_SOC_PCM3168A_I2C is not set ++# CONFIG_SND_SOC_PCM3168A_SPI is not set ++# CONFIG_SND_SOC_PCM5102A is not set ++# CONFIG_SND_SOC_PCM512x_I2C is not set ++# CONFIG_SND_SOC_PCM512x_SPI is not set ++# CONFIG_SND_SOC_PEB2466 is not set ++# CONFIG_SND_SOC_RK3328 is not set ++# CONFIG_SND_SOC_RT5616 is not set ++# CONFIG_SND_SOC_RT5631 is not set ++# CONFIG_SND_SOC_RT5640 is not set ++# CONFIG_SND_SOC_RT5659 is not set ++# CONFIG_SND_SOC_RT9120 is not set ++# CONFIG_SND_SOC_SGTL5000 is not set ++# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set ++# CONFIG_SND_SOC_SIMPLE_MUX is not set ++# CONFIG_SND_SOC_SMA1303 is not set ++# CONFIG_SND_SOC_SPDIF is not set ++# CONFIG_SND_SOC_SRC4XXX_I2C is not set ++# CONFIG_SND_SOC_SSM2305 is not set ++# CONFIG_SND_SOC_SSM2518 is not set ++# CONFIG_SND_SOC_SSM2602_SPI is not set ++# CONFIG_SND_SOC_SSM2602_I2C is not set ++# CONFIG_SND_SOC_SSM3515 is not set ++# CONFIG_SND_SOC_SSM4567 is not set ++# CONFIG_SND_SOC_STA32X is not set ++# CONFIG_SND_SOC_STA350 is not set ++# CONFIG_SND_SOC_STI_SAS is not set ++# CONFIG_SND_SOC_TAS2552 is not set ++# CONFIG_SND_SOC_TAS2562 is not set ++# CONFIG_SND_SOC_TAS2764 is not set ++# CONFIG_SND_SOC_TAS2770 is not set ++# CONFIG_SND_SOC_TAS2780 is not set ++# CONFIG_SND_SOC_TAS2781_I2C is not set ++# CONFIG_SND_SOC_TAS5086 is not set ++# CONFIG_SND_SOC_TAS571X is not set ++# CONFIG_SND_SOC_TAS5720 is not set ++# CONFIG_SND_SOC_TAS5805M is not set ++# CONFIG_SND_SOC_TAS6424 is not set ++# CONFIG_SND_SOC_TDA7419 is not set ++# CONFIG_SND_SOC_TFA9879 is not set ++# CONFIG_SND_SOC_TFA989X is not set ++# CONFIG_SND_SOC_TLV320ADC3XXX is not set ++# CONFIG_SND_SOC_TLV320AIC23_I2C is not set ++# CONFIG_SND_SOC_TLV320AIC23_SPI is not set ++# CONFIG_SND_SOC_TLV320AIC31XX is not set ++# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set ++# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set ++# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set ++# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set ++# CONFIG_SND_SOC_TLV320ADCX140 is not set ++# CONFIG_SND_SOC_TS3A227E is not set ++# CONFIG_SND_SOC_TSCS42XX is not set ++# CONFIG_SND_SOC_TSCS454 is not set ++# CONFIG_SND_SOC_UDA1334 is not set ++# CONFIG_SND_SOC_WM8510 is not set ++# CONFIG_SND_SOC_WM8523 is not set ++# CONFIG_SND_SOC_WM8524 is not set ++# CONFIG_SND_SOC_WM8580 is not set ++# CONFIG_SND_SOC_WM8711 is not set ++# CONFIG_SND_SOC_WM8728 is not set ++# CONFIG_SND_SOC_WM8731_I2C is not set ++# CONFIG_SND_SOC_WM8731_SPI is not set ++# CONFIG_SND_SOC_WM8737 is not set ++# CONFIG_SND_SOC_WM8741 is not set ++# CONFIG_SND_SOC_WM8750 is not set ++# CONFIG_SND_SOC_WM8753 is not set ++# CONFIG_SND_SOC_WM8770 is not set ++# CONFIG_SND_SOC_WM8776 is not set ++# CONFIG_SND_SOC_WM8782 is not set ++# CONFIG_SND_SOC_WM8804_I2C is not set ++# CONFIG_SND_SOC_WM8804_SPI is not set ++# CONFIG_SND_SOC_WM8903 is not set ++# CONFIG_SND_SOC_WM8904 is not set ++# CONFIG_SND_SOC_WM8940 is not set ++# CONFIG_SND_SOC_WM8960 is not set ++# CONFIG_SND_SOC_WM8961 is not set ++# CONFIG_SND_SOC_WM8962 is not set ++# CONFIG_SND_SOC_WM8974 is not set ++# CONFIG_SND_SOC_WM8978 is not set ++# CONFIG_SND_SOC_WM8985 is not set ++# CONFIG_SND_SOC_ZL38060 is not set ++# CONFIG_SND_SOC_MAX9759 is not set ++# CONFIG_SND_SOC_MT6351 is not set ++# CONFIG_SND_SOC_MT6358 is not set ++# CONFIG_SND_SOC_MT6660 is not set ++# CONFIG_SND_SOC_NAU8315 is not set ++# CONFIG_SND_SOC_NAU8540 is not set ++# CONFIG_SND_SOC_NAU8810 is not set ++# CONFIG_SND_SOC_NAU8821 is not set ++# CONFIG_SND_SOC_NAU8822 is not set ++# CONFIG_SND_SOC_NAU8824 is not set ++# CONFIG_SND_SOC_TPA6130A2 is not set ++# CONFIG_SND_SOC_LPASS_WSA_MACRO is not set ++# CONFIG_SND_SOC_LPASS_VA_MACRO is not set ++# CONFIG_SND_SOC_LPASS_RX_MACRO is not set ++# CONFIG_SND_SOC_LPASS_TX_MACRO is not set ++# end of CODEC drivers ++ ++# CONFIG_SND_SIMPLE_CARD is not set ++# CONFIG_SND_AUDIO_GRAPH_CARD is not set ++# CONFIG_SND_AUDIO_GRAPH_CARD2 is not set ++# CONFIG_SND_TEST_COMPONENT is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set @@ -410,7 +1529,19 @@ index 37f823d7d..e1e395754 100644 CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y -@@ -2839,7 +3018,60 @@ CONFIG_USB_DWC3_HOST=y +@@ -2119,9 +3241,9 @@ CONFIG_USB_STORAGE=y + # CONFIG_USB_CDNS_SUPPORT is not set + # CONFIG_USB_MUSB_HDRC is not set + CONFIG_USB_DWC3=y +-# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_HOST=y + # CONFIG_USB_DWC3_GADGET is not set +-CONFIG_USB_DWC3_DUAL_ROLE=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set + + # + # Platform Glue Driver Support +@@ -2134,7 +3256,60 @@ CONFIG_USB_DWC3_DUAL_ROLE=y # # USB port drivers # @@ -472,6 +1603,190 @@ index 37f823d7d..e1e395754 100644 # # USB Miscellaneous drivers +@@ -2219,6 +3394,10 @@ CONFIG_USB_CONFIGFS_MASS_STORAGE=y + # CONFIG_USB_CONFIGFS_F_LB_SS is not set + # CONFIG_USB_CONFIGFS_F_FS is not set + CONFIG_USB_CONFIGFS_F_UAC1=y ++# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set ++# CONFIG_USB_CONFIGFS_F_UAC2 is not set ++# CONFIG_USB_CONFIGFS_F_MIDI is not set ++# CONFIG_USB_CONFIGFS_F_MIDI2 is not set + # CONFIG_USB_CONFIGFS_F_HID is not set + CONFIG_USB_CONFIGFS_F_UVC=y + # CONFIG_USB_CONFIGFS_F_PRINTER is not set +@@ -2227,18 +3406,21 @@ CONFIG_USB_CONFIGFS_F_UVC=y + # USB Gadget precomposed configurations + # + # CONFIG_USB_ZERO is not set ++# CONFIG_USB_AUDIO is not set + # CONFIG_USB_ETH is not set + # CONFIG_USB_G_NCM is not set + # CONFIG_USB_GADGETFS is not set + # CONFIG_USB_FUNCTIONFS is not set + # CONFIG_USB_MASS_STORAGE is not set + # CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_MIDI_GADGET is not set + # CONFIG_USB_G_PRINTER is not set + # CONFIG_USB_CDC_COMPOSITE is not set + # CONFIG_USB_G_ACM_MS is not set + # CONFIG_USB_G_MULTI is not set + # CONFIG_USB_G_HID is not set + # CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set + # CONFIG_USB_RAW_GADGET is not set + # end of USB Gadget precomposed configurations + +@@ -2287,7 +3469,12 @@ CONFIG_EDAC_SUPPORT=y + # DMABUF options + # + # CONFIG_SYNC_FILE is not set ++# CONFIG_UDMABUF is not set ++# CONFIG_DMABUF_MOVE_NOTIFY is not set ++# CONFIG_DMABUF_DEBUG is not set ++# CONFIG_DMABUF_SELFTESTS is not set + # CONFIG_DMABUF_HEAPS is not set ++# CONFIG_DMABUF_SYSFS_STATS is not set + # end of DMABUF options + + # CONFIG_UIO is not set +@@ -2360,12 +3547,31 @@ CONFIG_ARM_TIMER_SP804=y + # end of Clock Source drivers + + # CONFIG_MAILBOX is not set ++CONFIG_IOMMU_IOVA=y ++CONFIG_IOMMU_API=y ++CONFIG_IOMMU_SUPPORT=y ++ ++# ++# Generic IOMMU Pagetable Support ++# ++CONFIG_IOMMU_IO_PGTABLE=y ++CONFIG_IOMMU_IO_PGTABLE_LPAE=y ++# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set + CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y ++# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set ++# CONFIG_IOMMU_IO_PGTABLE_DART is not set ++# end of Generic IOMMU Pagetable Support ++ ++# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set + CONFIG_IOMMU_DEFAULT_DMA_LAZY=y ++# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set ++CONFIG_OF_IOMMU=y ++CONFIG_IOMMU_DMA=y ++CONFIG_IOMMU_SVA=y ++# CONFIG_IOMMUFD is not set ++# CONFIG_ARM_SMMU is not set + CONFIG_ARM_SMMU_V3=y + CONFIG_ARM_SMMU_V3_SVA=y +-# CONFIG_NVMEM is not set +-CONFIG_VENDOR_NPU=y + + # + # Remoteproc drivers +@@ -2503,6 +3709,7 @@ CONFIG_GENERIC_PHY=y + # CONFIG_ANDROID_BINDER_IPC is not set + # end of Android + ++# CONFIG_LIBNVDIMM is not set + # CONFIG_DAX is not set + # CONFIG_NVMEM is not set + +@@ -2548,6 +3755,7 @@ CONFIG_MMC_SDHCI_NEBULA=y + # CONFIG_MMC_SDHCI_ANT is not set + # CONFIG_CMA_MEM_SHARED is not set + # CONFIG_CMA_ADVANCE_SHARE is not set ++CONFIG_VENDOR_NPU=y + # end of Vendor driver support + # end of Device Drivers + +@@ -2701,8 +3909,20 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 + # CONFIG_EROFS_FS is not set + CONFIG_NETWORK_FILESYSTEMS=y + CONFIG_NFS_FS=y +-CONFIG_NLS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_NFS_DISABLE_UDP_SUPPORT=y + # CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++CONFIG_RPCSEC_GSS_KRB5=y ++# CONFIG_SUNRPC_DEBUG is not set + # CONFIG_CEPH_FS is not set + # CONFIG_CIFS is not set + # CONFIG_SMB_SERVER is not set +@@ -2793,13 +4013,16 @@ CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf" + # Memory initialization + # + CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +-CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER=y ++CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y + CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y + CONFIG_INIT_STACK_NONE=y + # CONFIG_INIT_STACK_ALL_PATTERN is not set + # CONFIG_INIT_STACK_ALL_ZERO is not set ++# CONFIG_GCC_PLUGIN_STACKLEAK is not set + # CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set + # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set ++CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y ++# CONFIG_ZERO_CALL_USED_REGS is not set + # end of Memory initialization + + # +@@ -2810,6 +4033,8 @@ CONFIG_INIT_STACK_NONE=y + # end of Hardening of kernel data structures + + CONFIG_RANDSTRUCT_NONE=y ++# CONFIG_RANDSTRUCT_FULL is not set ++# CONFIG_RANDSTRUCT_PERFORMANCE is not set + # end of Kernel hardening options + # end of Security options + +@@ -3090,15 +4315,20 @@ CONFIG_XZ_DEC=y + # CONFIG_XZ_DEC_MICROLZMA is not set + # CONFIG_XZ_DEC_TEST is not set + CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_INTERVAL_TREE=y ++CONFIG_XARRAY_MULTI=y + CONFIG_ASSOCIATIVE_ARRAY=y + CONFIG_HAS_IOMEM=y + CONFIG_HAS_IOPORT=y + CONFIG_HAS_DMA=y ++CONFIG_DMA_OPS=y ++CONFIG_NEED_SG_DMA_FLAGS=y + CONFIG_NEED_SG_DMA_LENGTH=y + CONFIG_NEED_DMA_MAP_STATE=y + CONFIG_ARCH_DMA_ADDR_T_64BIT=y + CONFIG_DMA_DECLARE_COHERENT=y + CONFIG_ARCH_HAS_SETUP_DMA_OPS=y ++CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y + CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y + CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y + CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +@@ -3129,6 +4359,7 @@ CONFIG_GLOB=y + CONFIG_NLATTR=y + # CONFIG_IRQ_POLL is not set + CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y + CONFIG_HAVE_GENERIC_VDSO=y + CONFIG_GENERIC_GETTIMEOFDAY=y + CONFIG_GENERIC_VDSO_TIME_NS=y +@@ -3174,7 +4405,9 @@ CONFIG_DEBUG_INFO_NONE=y + # CONFIG_DEBUG_INFO_DWARF5 is not set + CONFIG_FRAME_WARN=2048 + # CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set + # CONFIG_HEADERS_INSTALL is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set + CONFIG_SECTION_MISMATCH_WARN_ONLY=y + # CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set + CONFIG_ARCH_WANT_FRAME_POINTERS=y diff --git a/drivers/net/ethernet/vendor/gmac/gmac.h b/drivers/net/ethernet/vendor/gmac/gmac.h index 52a472311..d1132ce13 100644 --- a/drivers/net/ethernet/vendor/gmac/gmac.h diff --git a/vendor/zsks/patch/gcc/Makefile b/vendor/zsks/patch/gcc/Makefile index ba5bd9d3cc93aecc45374535fa6bbd7475569302..7d50451d57a4f5b6db9ff9aa796dde5c7a518f4f 100755 --- a/vendor/zsks/patch/gcc/Makefile +++ b/vendor/zsks/patch/gcc/Makefile @@ -5,7 +5,6 @@ CHIP ?= ss928v100 KERNEL_ORIGIN_VER:=linux-6.6.86 KERNEL_VER:=linux-6.6.y -HiEulerPi_KERNEL_PATCH:=HiEulerPI_gcc_linux-6.6.y.patch LLVM ?= 0 ARCH_TYPE ?= arm64 @@ -40,8 +39,7 @@ ifneq ($(BUILD_DIR)/$(KERNEL_VER), $(wildcard $(BUILD_DIR)/$(KERNEL_VER))) @echo -e $(GREEN)"patching kernel..." $(DONE) pushd $(BUILD_DIR);mv $(KERNEL_ORIGIN_VER) $(KERNEL_VER);popd pushd $(BUILD_DIR)/$(KERNEL_VER); patch -p1< ../$(KERNEL_ORIGIN_VER).patch;popd - @echo -e $(GREEN)"patching kernel for HiEulerPi ..." $(DONE) - pushd $(BUILD_DIR)/$(KERNEL_VER); patch -p1< ../$(HiEulerPi_KERNEL_PATCH);popd + @echo -e $(GREEN)"patching kernel for ZSKS ..." $(DONE) pushd $(BUILD_DIR)/$(KERNEL_VER);patch -p1< ../0001-zsks-gcc-linux-6.6.y.patch;popd endif $(MAKE) -C $(BUILD_DIR)/$(KERNEL_VER) ARCH=$(ARCH_TYPE) $(COMPILE_OPTIONS) $(KERNEL_CFG) diff --git a/vendor/zsks/patch/gcc/load_ss928v100_ubuntu b/vendor/zsks/patch/gcc/load_ss928v100_ubuntu new file mode 100755 index 0000000000000000000000000000000000000000..cc6b4622e28b739e9d365baca9dcc19da2c5e344 --- /dev/null +++ b/vendor/zsks/patch/gcc/load_ss928v100_ubuntu @@ -0,0 +1,250 @@ +#!/bin/sh +# Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Usage: ./load_ss928v100 [ -r|-i|-a ] [ -sensor0~3 ] +# -r : rmmod all modules +# -i : insmod all modules +# -a : rmmod all moules and then insmod them +# e.g: ./load_ss928v100 -i -sensor0 hy_s0603 -sensor1 hy_s0603 -sensor2 hy_s0603 -sensor3 hy_s0603 + +####### select sensor type for your test ######################## +#### hy_s0603 #### +####################Variables Definition########################## + +SNS_TYPE0=hy_s0603; # sensor type +SNS_TYPE1=hy_s0603; # sensor type +SNS_TYPE2=hy_s0603; # sensor type +SNS_TYPE3=hy_s0603; # sensor type + +#DDR start:0x40000000, IPCM(2M); DSP(62M); MCU(192M); kernel start:0x50000000, OS(512M); MMZ start:0x70000000 +mem_total=4096 # 4096M, total mem +mem_start=0x40000000 # phy mem start +ipcm_mem_size=2 # 2M, ipcm mem +dsp_mem_size=62 # 62M, dsp mem +mcu_mem_size=192 # 192M, mcu mem +os_mem_size=1024 # 512M, os mem + +mmz_start=0x90000000; # mmz start addr +mmz_size=2816M; # 3328M, mmz size + +reserve_mem_size=0 # 0M, reserve mmz size +################################################################## + +function report_error() +{ + echo "******* Error: There's something wrong, please check! *****" + exit 1 +} + +function insert_security_subsys() +{ + insmod ot_cipher.ko + insmod ot_klad.ko + insmod ot_otp.ko +} + +function remove_security_subsys() +{ + rmmod ot_otp + rmmod ot_klad.ko + rmmod ot_cipher.ko +} + +function insert_ko() +{ + # sys config + insmod sys_config.ko sensors=sns0=$SNS_TYPE0,sns1=$SNS_TYPE1,sns2=$SNS_TYPE2,sns3=$SNS_TYPE3 + # driver load + insmod ot_osal.ko anony=1 mmz_allocator=ot mmz=anonymous,0,0x90000000,2816M$1 mem_process_isolation=0 || report_error + insmod ot_irq.ko + insmod ot_user_proc.ko + insmod ot_base.ko + insmod ot_sys.ko + insmod ot_tde.ko + insmod ot_vo.ko + insmod svp_npu/ot_svp_npu.ko + # gfbg: default fb0:argb1555,3840x2160,2buf;fb1:argb8888,1920x1080,2buf;fb2:clut4,3840x2160,1buf + insmod gfbg.ko video="gfbg:vram0_size:32400,vram1_size:16200,vram3_size:4052" + + insmod ot_hdmi.ko + insmod ot_mipi_tx.ko g_smooth=0 + insmod ot_mipi_rx.ko + + insert_security_subsys +} + +function remove_ko() +{ + remove_security_subsys + + rmmod ot_mipi_rx + rmmod ot_mipi_tx + rmmod ot_hdmi + rmmod gfbg + rmmod svp_npu/ot_svp_npu.ko + rmmod ot_vo + rmmod ot_tde + rmmod ot_sys + rmmod ot_base + rmmod ot_user_proc + rmmod ot_irq + rmmod ot_osal + rmmod sys_config +} + +load_usage() +{ + echo "Usage: $0 [-option] [-sensor0~3] " + echo "options:" + echo " -i insert modules" + echo " -r remove modules" + echo " -a remove modules first, then insert modules" + echo " -sensor0~3 sensor_name config sensor type [default: hy_s0603]" + echo " -total mem_size config total mem size [unit: M, default: 4096]" + echo " -osmem os_mem_size config os mem size [unit: M, default: 512]" + echo " -h help information" + echo -e "Available sensors: hy_s0603" + echo -e "for example: $0 -i -sensor0 hy_s0603 -sensor1 hy_s0603 -sensor2 hy_s0603 -sensor3 hy_s0603 -total 4096 -osmem 512\n" +} + +function calc_mmz_info() +{ + mmz_start=`echo "$mem_start $os_mem_size $mcu_mem_size $dsp_mem_size $ipcm_mem_size" | + awk 'BEGIN { temp = 0; } + { + temp = $1/1024/1024 + $2 + $3 + $4 + $5; + } + END { printf("0x%x00000\n", temp); }'` + + mmz_size=`echo "$mem_total $os_mem_size $mcu_mem_size $dsp_mem_size $ipcm_mem_size $reserve_mem_size" | + awk 'BEGIN { temp = 0; } + { + temp = $1 - $2 - $3 - $4 - $5 - $6; + } + END { printf("%dM\n", temp); }'` + echo "mmz_start: $mmz_start, mmz_size: $mmz_size" +} + +b_arg_insmod=0 +b_arg_remove=0 +function parse_arg() +{ + ######################parse arg################################### + b_arg_sensor0=0 + b_arg_sensor1=0 + b_arg_sensor2=0 + b_arg_sensor3=0 + b_arg_total_mem=0 + b_arg_os_mem=0 + + for arg in $@ + do + if [ $b_arg_sensor0 -eq 1 ] ; then + b_arg_sensor0=0; + SNS_TYPE0=$arg; + fi + if [ $b_arg_sensor1 -eq 1 ] ; then + b_arg_sensor1=0; + SNS_TYPE1=$arg; + fi + if [ $b_arg_sensor2 -eq 1 ] ; then + b_arg_sensor2=0; + SNS_TYPE2=$arg; + fi + if [ $b_arg_sensor3 -eq 1 ] ; then + b_arg_sensor3=0; + SNS_TYPE3=$arg; + fi + + if [ $b_arg_total_mem -eq 1 ]; then + b_arg_total_mem=0; + mem_total=$arg; + + if [ -z $mem_total ]; then + echo "[error] mem_total is null" + exit; + fi + fi + + if [ $b_arg_os_mem -eq 1 ] ; then + b_arg_os_mem=0; + os_mem_size=$arg; + + if [ -z $os_mem_size ]; then + echo "[error] os_mem_size is null" + exit; + fi + fi + + case $arg in + "-i") + b_arg_insmod=1; + ;; + "-r") + b_arg_remove=1; + ;; + "-a") + b_arg_insmod=1; + b_arg_remove=1; + ;; + "-h") + load_usage; + ;; + "-sensor0") + b_arg_sensor0=1; + ;; + "-sensor") + b_arg_sensor0=1; + ;; + "-sensor1") + b_arg_sensor1=1; + ;; + "-sensor2") + b_arg_sensor2=1; + ;; + "-sensor3") + b_arg_sensor3=1; + ;; + "-osmem") + b_arg_os_mem=1; + ;; + "-total") + b_arg_total_mem=1; + ;; + esac + done + + if [ $os_mem_size -ge $((mem_total - dsp_mem_size - reserve_mem_size)) ] ; then + echo "[err] os_mem[$os_mem_size], over total_mem[$mem_total] - dsp_mem[$dsp_mem_size] - reserve_mem[$reserve_mem_size]" + exit; + fi + #######################parse arg end######################## +} + +if [ $# -lt 1 ]; then + load_usage; + exit 0; +fi + +parse_arg $@ + +calc_mmz_info; + +#######################Action############################### +if [ $b_arg_remove -eq 1 ]; then + remove_ko; +fi + +if [ $b_arg_insmod -eq 1 ]; then + insert_ko; +fi diff --git a/vendor/zsks/patch_build.sh b/vendor/zsks/patch_build.sh index c6cb1d28e9fa5d51f7d24a353e564492a35e1314..939768249673d4d05fe42400b296486e2ffde288 100755 --- a/vendor/zsks/patch_build.sh +++ b/vendor/zsks/patch_build.sh @@ -68,7 +68,8 @@ apply_common_ohos_files() { cp -rf "${src_dir}/bootargs" "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/uboot/" cp -rf "${src_dir}/boot_image_4GB.bin" "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/uboot/" cp -rf "${src_dir}/emmc_burn_table.xml" "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/uboot/" - + + # 删掉下面4行,就可以编译出带桌面版本的openharmony镜像 cp -rf "${src_dir}/init_linux_openharmony.cfg" "${OHOS_PATH}/vendor/hisilicon/hispark_aifly_linux/init_configs/" cp -rf "${src_dir}/S82ohos" "${OHOS_PATH}/vendor/hisilicon/hispark_aifly_linux/init_configs/etc/init.d/" cp -rf "${src_dir}/config.json" "${OHOS_PATH}/vendor/hisilicon/hispark_aifly_linux/" @@ -89,9 +90,9 @@ apply_clang_patch() { need_dir "$EBAINA_PATH" need_dir "$CLANG_SDK_PATH" need_dir "$CLANG_PATCH_DIR" - need_file "${CLANG_PATCH_DIR}/0001-support-USB-Camera-and-zsks-demo.patch" + need_file "${CLANG_PATCH_DIR}/0001-support-USB-Camera-and-mipi-camera.patch" - ( cd "$EBAINA_PATH" && chmod +x patch_build.sh && ./patch_build.sh -clang ) + ( cd "$EBAINA_PATH" ) # 解压并拷贝 sensor libs 到 OHOS clang SDK 的 mpp/out/lib local clang_patch_dir="${EBAINA_PATH}/patch/ss928v100_clang" @@ -100,22 +101,25 @@ apply_clang_patch() { ( cd "$clang_patch_dir" && tar xvf sensor_libs.tar.xz ) if [ -d "${clang_patch_dir}/sensor_libs" ]; then - mv -f "${clang_patch_dir}/sensor_libs/"* "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/sdk_linux/smp/a55_linux/mpp/out/lib" + cp -rf "${clang_patch_dir}/sensor_libs/"* "${CLANG_SDK_PATH}/smp/a55_linux/mpp/out/lib/" + if [ -d "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/sdk_linux/smp/a55_linux/mpp/out/lib" ]; then + mv -f "${clang_patch_dir}/sensor_libs/"* "${OHOS_PATH}/device/soc/hisilicon/hi3403v100/sdk_linux/smp/a55_linux/mpp/out/lib" + fi rm -rf "${clang_patch_dir}/sensor_libs" fi apply_common_ohos_files "$CLANG_PATCH_DIR" - ( cd "$CLANG_SDK_PATH" && patch -p1 < "${CLANG_PATCH_DIR}/0001-support-USB-Camera-and-zsks-demo.patch" ) + ( cd "$CLANG_SDK_PATH" && patch -p1 < "${CLANG_PATCH_DIR}/0001-support-USB-Camera-and-mipi-camera.patch" ) } apply_gcc_patch() { need_dir "$EBAINA_PATH" need_dir "$GCC_SDK_PATH" need_dir "$GCC_PATCH_DIR" - need_file "${GCC_PATCH_DIR}/0001-support-USB-Camera-and-zsks-demo.patch" + need_file "${GCC_PATCH_DIR}/0001-support-USB-Camera-and-mipi-camera.patch" - ( cd "$EBAINA_PATH" && chmod +x patch_build.sh && ./patch_build.sh -gcc ) + ( cd "$EBAINA_PATH" ) local gcc_patch_dir="${EBAINA_PATH}/patch/ss928v100_gcc" need_dir "$gcc_patch_dir" @@ -128,7 +132,7 @@ apply_gcc_patch() { fi copy_gcc_linux_open_source_files - ( cd "$GCC_SDK_PATH" && patch -p1 < "${GCC_PATCH_DIR}/0001-support-USB-Camera-and-zsks-demo.patch" ) + ( cd "$GCC_SDK_PATH" && patch -p1 < "${GCC_PATCH_DIR}/0001-support-USB-Camera-and-mipi-camera.patch" ) } main() { @@ -158,4 +162,4 @@ main() { echo "✓ 完成" } -main "$@" \ No newline at end of file +main "$@" diff --git a/vendor/zsks/pic/image-20260421151736921.png b/vendor/zsks/pic/image-20260421151736921.png index a253a56182cdc5115f2f2a98c1df318b14d5831f..a607c3f04d6095be2f4304d2de12c61642e4d207 100755 Binary files a/vendor/zsks/pic/image-20260421151736921.png and b/vendor/zsks/pic/image-20260421151736921.png differ