#ifndef MEDIAPIPE_FRAMEWORK_API2_BUILDER_H_ #define MEDIAPIPE_FRAMEWORK_API2_BUILDER_H_ #include <functional> #include <map> #include <memory> #include <optional> #include <string> #include <type_traits> #include <utility> #include <vector> #include "absl/container/btree_map.h" #include "absl/log/absl_check.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/message_lite.h" #include "mediapipe/framework/api2/packet.h" #include "mediapipe/framework/api2/port.h" #include "mediapipe/framework/calculator_base.h" #include "mediapipe/framework/calculator_contract.h" #include "mediapipe/framework/mediapipe_options.pb.h" #include "mediapipe/framework/port/any_proto.h" #include "mediapipe/framework/port/ret_check.h" #include "mediapipe/framework/stream_handler.pb.h" namespace mediapipe { namespace api2 { namespace builder { // Workaround for static_assert(false). Example: // dependent_false<T>::value returns false. // For more information, see: // https://en.cppreference.com/w/cpp/language/if#Constexpr_If // TODO: migrate to a common utility when available. template <class T> struct dependent_false : std::false_type { … }; template <typename T> T& GetWithAutoGrow(std::vector<std::unique_ptr<T>>* vecp, size_t index) { … } struct TagIndexLocation { … }; template <typename T> class TagIndexMap { … }; class Graph; class NodeBase; class PacketGenerator; // These structs are used internally to store information about the endpoints // of a connection. struct SourceBase; struct DestinationBase { … }; struct SourceBase { … }; // Following existing GraphConfig usage, we allow using a multiport as a single // port as well. This is necessary for generic nodes, since we have no // information about which ports are meant to be multiports or not, but it is // also convenient with typed nodes. template <typename Single> class MultiPort : public Single { … }; namespace internal_builder { template <typename T, typename U> using AllowCast = std::integral_constant<bool, (std::is_same_v<T, AnyType> || std::is_same_v<U, AnyType>) && !std::is_same_v<T, U>>; } // namespace internal_builder template <bool IsSide, typename T = internal::Generic> class SourceImpl; // These classes wrap references to the underlying source/destination // endpoints, adding type information and the user-visible API. template <bool IsSide, typename T = internal::Generic> class DestinationImpl { … }; template <bool IsSide, typename T> class SourceImpl { … }; // A source and a destination correspond to an output/input stream on a node, // and a side source and side destination correspond to an output/input side // packet. // For graph inputs/outputs, however, the inputs are sources, and the outputs // are destinations. This is because graph ports are connected "from inside" // when building the graph. Source; // Represents a stream of packets of a particular type. // // The intended use: // - decouple input/output streams from graph/node during graph construction // - pass streams around and connect them as needed, extracting reusable parts // to utility/convenience functions or classes. // // For example: // Stream<Image> Resize(Stream<Image> image, const Size& size, Graph& graph) { // auto& scaler_node = graph.AddNode("GlScalerCalculator"); // auto& opts = scaler_node.GetOptions<GlScalerCalculatorOptions>(); // opts.set_output_width(size.width); // opts.set_output_height(size.height); // a >> scaler_node.In("IMAGE"); // return scaler_node.Out("IMAGE").Cast<Image>(); // } // // Where graph can use it as: // Graph graph; // Stream<Image> input_image = graph.In("INPUT_IMAGE").Cast<Image>(); // Stream<Image> resized_image = Resize(input_image, {64, 64}, graph); template <typename T> using Stream = Source<T>; template <typename T = internal::Generic> using MultiSource = MultiPort<Source<T>>; SideSource; // Represents a side packet of a particular type. // // The intended use: // - decouple input/output side packets from graph/node during graph // construction // - pass side packets around and connect them as needed, extracting reusable // parts utility/convenience functions or classes. // // For example: // SidePacket<TfLiteModelPtr> GetModel(SidePacket<std::string> model_blob, // Graph& graph) { // auto& model_node = graph.AddNode("TfLiteModelCalculator"); // model_blob >> model_node.SideIn("MODEL_BLOB"); // return model_node.SideOut("MODEL").Cast<TfLiteModelPtr>(); // } // // Where graph can use it as: // Graph graph; // SidePacket<std::string> model_blob = // graph.SideIn("MODEL_BLOB").Cast<std::string>(); // SidePacket<TfLiteModelPtr> model = GetModel(model_blob, graph); template <typename T> using SidePacket = SideSource<T>; template <typename T = internal::Generic> using MultiSideSource = MultiPort<SideSource<T>>; Destination; SideDestination; template <typename T = internal::Generic> using MultiDestination = MultiPort<Destination<T>>; template <typename T = internal::Generic> using MultiSideDestination = MultiPort<SideDestination<T>>; namespace internal_builder { template <typename OptionsT> OptionsT& GetOptions(std::optional<mediapipe::MediaPipeOptions>& options) { … } } // namespace internal_builder class Executor { … }; class NodeBase; class InputStreamHandler { … }; class OutputStreamHandler { … }; class NodeBase { … }; template <class Calc = internal::Generic> class Node; #if __cplusplus >= 201703L // Deduction guide to silence -Wctad-maybe-unsupported. explicit Node() -> Node<internal::Generic>; #endif // C++17 template <> class Node<internal::Generic> : public NodeBase { public: Node(std::string type) : NodeBase(std::move(type)) {} }; using GenericNode = Node<internal::Generic>; template <class Calc> class Node : public NodeBase { … }; // For legacy PacketGenerators. class PacketGenerator { … }; class Graph { … }; } // namespace builder } // namespace api2 } // namespace mediapipe #endif // MEDIAPIPE_FRAMEWORK_API2_BUILDER_H_