Project import generated by Copybara.
GitOrigin-RevId: d8caa66de45839696f5bd0786ad3bfbcb9cff632
This commit is contained in:
@@ -600,6 +600,123 @@ cc_library(
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "container_util",
|
||||
srcs = ["container_util.cc"],
|
||||
hdrs = ["container_util.h"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":name_util",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/tool:switch_container_cc_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "switch_demux_calculator",
|
||||
srcs = ["switch_demux_calculator.cc"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
":container_util",
|
||||
":options_util",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:collection_item_id",
|
||||
"//mediapipe/framework/deps:mathutil",
|
||||
"//mediapipe/framework/formats:video_stream_header",
|
||||
"//mediapipe/framework/port:integral_types",
|
||||
"//mediapipe/framework/port:logging",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "switch_mux_calculator",
|
||||
srcs = ["switch_mux_calculator.cc"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
":container_util",
|
||||
":options_util",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:collection_item_id",
|
||||
"//mediapipe/framework:input_stream_shard",
|
||||
"//mediapipe/framework:output_stream_shard",
|
||||
"//mediapipe/framework/deps:mathutil",
|
||||
"//mediapipe/framework/formats:video_stream_header",
|
||||
"//mediapipe/framework/port:integral_types",
|
||||
"//mediapipe/framework/port:logging",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
mediapipe_proto_library(
|
||||
name = "switch_container_proto",
|
||||
srcs = ["switch_container.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_options_proto",
|
||||
"//mediapipe/framework:calculator_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "switch_container",
|
||||
srcs = ["switch_container.cc"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":container_util",
|
||||
":name_util",
|
||||
":subgraph_expansion",
|
||||
":switch_demux_calculator",
|
||||
":switch_mux_calculator",
|
||||
"//mediapipe/framework:calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:mediapipe_options_cc_proto",
|
||||
"//mediapipe/framework:stream_handler_cc_proto",
|
||||
"//mediapipe/framework:subgraph",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/stream_handler:sync_set_input_stream_handler_cc_proto",
|
||||
"//mediapipe/framework/tool:switch_container_cc_proto",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "switch_container_test",
|
||||
size = "small",
|
||||
srcs = ["switch_container_test.cc"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":node_chain_subgraph_cc_proto",
|
||||
":subgraph_expansion",
|
||||
":switch_container",
|
||||
"//mediapipe/calculators/core:pass_through_calculator",
|
||||
"//mediapipe/framework:calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:subgraph",
|
||||
"//mediapipe/framework:test_calculators",
|
||||
"//mediapipe/framework/deps:message_matchers",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"//mediapipe/framework/port:logging",
|
||||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/stream_handler:immediate_input_stream_handler",
|
||||
],
|
||||
)
|
||||
|
||||
exports_files(
|
||||
["build_defs.bzl"],
|
||||
visibility = ["//mediapipe/framework:__subpackages__"],
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "mediapipe/framework/tool/container_util.h"
|
||||
|
||||
#include "mediapipe/framework/tool/switch_container.pb.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
std::string ChannelTag(const std::string& tag, int channel) {
|
||||
return absl::StrCat("C", channel, "__", tag);
|
||||
}
|
||||
|
||||
// Parses a tag name starting with a channel prefix, like "C2__".
|
||||
bool ParseChannelTag(const std::string& channel_name, std::string* name,
|
||||
std::string* num) {
|
||||
int pos = channel_name.find("C");
|
||||
int sep = channel_name.find("__");
|
||||
if (pos != 0 || sep == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
*num = channel_name.substr(pos + 1, sep - (pos + 1));
|
||||
*name = channel_name.substr(sep + 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> ChannelTags(const std::shared_ptr<tool::TagMap>& map) {
|
||||
std::set<std::string> result;
|
||||
for (const std::string& tag : map->GetTags()) {
|
||||
std::string name, num;
|
||||
if (ParseChannelTag(tag, &name, &num)) {
|
||||
result.insert(name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ChannelCount(const std::shared_ptr<tool::TagMap>& map) {
|
||||
int count = 0;
|
||||
for (const std::string& tag : map->GetTags()) {
|
||||
std::string name, num;
|
||||
int channel = -1;
|
||||
if (ParseChannelTag(tag, &name, &num)) {
|
||||
if (absl::SimpleAtoi(num, &channel)) {
|
||||
count = std::max(count, channel + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void Relay(const InputStreamShard& input, OutputStreamShard* output) {
|
||||
if (input.IsEmpty()) {
|
||||
Timestamp input_bound = input.Value().Timestamp().NextAllowedInStream();
|
||||
if (output->NextTimestampBound() < input_bound) {
|
||||
output->SetNextTimestampBound(input_bound);
|
||||
}
|
||||
} else {
|
||||
output->AddPacket(input.Value());
|
||||
}
|
||||
}
|
||||
|
||||
int GetChannelIndex(const CalculatorContext& cc, int previous_index) {
|
||||
int result = previous_index;
|
||||
Packet select_packet;
|
||||
Packet enable_packet;
|
||||
if (cc.InputTimestamp() == Timestamp::Unstarted()) {
|
||||
auto& options = cc.Options<mediapipe::SwitchContainerOptions>();
|
||||
if (options.has_enable()) {
|
||||
result = options.enable() ? 1 : 0;
|
||||
}
|
||||
if (options.has_select()) {
|
||||
result = options.select();
|
||||
}
|
||||
if (cc.InputSidePackets().HasTag("ENABLE")) {
|
||||
enable_packet = cc.InputSidePackets().Tag("ENABLE");
|
||||
}
|
||||
if (cc.InputSidePackets().HasTag("SELECT")) {
|
||||
select_packet = cc.InputSidePackets().Tag("SELECT");
|
||||
}
|
||||
} else {
|
||||
if (cc.Inputs().HasTag("ENABLE")) {
|
||||
enable_packet = cc.Inputs().Tag("ENABLE").Value();
|
||||
}
|
||||
if (cc.Inputs().HasTag("SELECT")) {
|
||||
select_packet = cc.Inputs().Tag("SELECT").Value();
|
||||
}
|
||||
}
|
||||
if (!enable_packet.IsEmpty()) {
|
||||
result = enable_packet.Get<bool>() ? 1 : 0;
|
||||
}
|
||||
if (!select_packet.IsEmpty()) {
|
||||
result = select_packet.Get<int>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef MEDIAPIPE_FRAMEWORK_TOOL_CONTAINER_UTIL_H_
|
||||
#define MEDIAPIPE_FRAMEWORK_TOOL_CONTAINER_UTIL_H_
|
||||
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
// Returns a tag name for one of the demux output channels.
|
||||
// This is the channel number followed by the stream name separated by "__".
|
||||
// For example, the channel-name for stream "FRAME" on channel 1 is "C1__FRAME".
|
||||
std::string ChannelTag(const std::string& tag, int channel);
|
||||
|
||||
// Returns the set of tags directed to demux output channels.
|
||||
// Each demux output tag is named using function ChannelTag().
|
||||
// This function returns the demux input tags without the channel numbers.
|
||||
std::set<std::string> ChannelTags(const std::shared_ptr<tool::TagMap>& map);
|
||||
|
||||
// Returns the number of demux output channels.
|
||||
int ChannelCount(const std::shared_ptr<tool::TagMap>& map);
|
||||
|
||||
// Copies packet or timestamp bound from input to output stream.
|
||||
void Relay(const InputStreamShard& input, OutputStreamShard* output);
|
||||
|
||||
// Returns the most recent specified channel index.
|
||||
int GetChannelIndex(const CalculatorContext& cc, int previous_index);
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
#endif // MEDIAPIPE_FRAMEWORK_TOOL_CONTAINER_UTIL_H_
|
||||
@@ -25,14 +25,14 @@
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
::mediapipe::StatusOr<std::unique_ptr<PacketSet>> FillPacketSet(
|
||||
mediapipe::StatusOr<std::unique_ptr<PacketSet>> FillPacketSet(
|
||||
const PacketTypeSet& input_side_packet_types,
|
||||
const std::map<std::string, Packet>& input_side_packets,
|
||||
int* missing_packet_count_ptr) {
|
||||
if (missing_packet_count_ptr != nullptr) {
|
||||
*missing_packet_count_ptr = 0;
|
||||
}
|
||||
std::vector<::mediapipe::Status> errors;
|
||||
std::vector<mediapipe::Status> errors;
|
||||
auto packet_set =
|
||||
absl::make_unique<PacketSet>(input_side_packet_types.TagMap());
|
||||
const auto& names = input_side_packet_types.TagMap()->Names();
|
||||
@@ -44,20 +44,20 @@ namespace tool {
|
||||
if (missing_packet_count_ptr != nullptr) {
|
||||
++(*missing_packet_count_ptr);
|
||||
} else {
|
||||
errors.push_back(::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
errors.push_back(mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Missing input side packet: " << name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
packet_set->Get(id) = iter->second;
|
||||
// Check the type.
|
||||
::mediapipe::Status status =
|
||||
mediapipe::Status status =
|
||||
input_side_packet_types.Get(id).Validate(iter->second);
|
||||
if (!status.ok()) {
|
||||
std::pair<std::string, int> tag_index =
|
||||
input_side_packet_types.TagAndIndexFromId(id);
|
||||
errors.push_back(
|
||||
::mediapipe::StatusBuilder(status, MEDIAPIPE_LOC).SetPrepend()
|
||||
mediapipe::StatusBuilder(status, MEDIAPIPE_LOC).SetPrepend()
|
||||
<< "Packet \""
|
||||
<< input_side_packet_types.TagMap()->Names()[id.value()]
|
||||
<< "\" with tag \"" << tag_index.first << "\" and index "
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace tool {
|
||||
// missing_packet_count_ptr is not null, the number of missing packets
|
||||
// is returned in *missing_packet_count_ptr. Otherwise, an error is
|
||||
// returned if any packets are missing.
|
||||
::mediapipe::StatusOr<std::unique_ptr<PacketSet>> FillPacketSet(
|
||||
mediapipe::StatusOr<std::unique_ptr<PacketSet>> FillPacketSet(
|
||||
const PacketTypeSet& input_side_packet_types,
|
||||
const std::map<std::string, Packet>& input_side_packets,
|
||||
int* missing_packet_count_ptr);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option java_package = "com.google.mediapipe.proto";
|
||||
option java_outer_classname = "GateSubgraphProto";
|
||||
|
||||
// Options for a gate-subgraph directing traffic to one of several contained
|
||||
// CalculatorGraphConfig's.
|
||||
message GateSubgraphOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional GateSubgraphOptions ext = 297196839;
|
||||
}
|
||||
|
||||
// The contained literal subgraph configuration(s).
|
||||
repeated CalculatorGraphConfig contained_graph = 1;
|
||||
|
||||
// The contained registered subgraphs or calculators.
|
||||
repeated CalculatorGraphConfig.Node contained_node = 2;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ std::string GetUnusedSidePacketName(
|
||||
}
|
||||
std::string candidate = input_side_packet_name_base;
|
||||
int iter = 2;
|
||||
while (::mediapipe::ContainsKey(input_side_packets, candidate)) {
|
||||
while (mediapipe::ContainsKey(input_side_packets, candidate)) {
|
||||
candidate = absl::StrCat(input_side_packet_name_base, "_",
|
||||
absl::StrFormat("%02d", iter));
|
||||
++iter;
|
||||
@@ -116,7 +116,9 @@ std::pair<std::string, int> ParseTagIndexFromStream(const std::string& stream) {
|
||||
}
|
||||
|
||||
std::string CatTag(const std::string& tag, int index) {
|
||||
return absl::StrCat(tag, index <= 0 ? "" : absl::StrCat(":", index));
|
||||
std::string colon_index =
|
||||
(index <= 0 || tag.empty()) ? "" : absl::StrCat(":", index);
|
||||
return absl::StrCat(tag, colon_index);
|
||||
}
|
||||
|
||||
std::string CatStream(const std::pair<std::string, int>& tag_index,
|
||||
|
||||
@@ -93,7 +93,7 @@ std::string CatStream(const std::pair<std::string, int>& tag_index,
|
||||
} // namespace mediapipe
|
||||
|
||||
namespace mediapipe {
|
||||
using ::mediapipe::tool::CanonicalNodeName;
|
||||
using mediapipe::tool::CanonicalNodeName;
|
||||
} // namespace mediapipe
|
||||
|
||||
#endif // MEDIAPIPE_FRAMEWORK_TOOL_NAME_UTIL_H_
|
||||
|
||||
@@ -85,7 +85,7 @@ void GetNodeOptions(const CalculatorGraphConfig::Node& node_config, T* result) {
|
||||
#if defined(MEDIAPIPE_PROTO_LITE) && defined(MEDIAPIPE_PROTO_THIRD_PARTY)
|
||||
// protobuf::Any is unavailable with third_party/protobuf:protobuf-lite.
|
||||
#else
|
||||
for (const ::mediapipe::protobuf::Any& options : node_config.node_options()) {
|
||||
for (const mediapipe::protobuf::Any& options : node_config.node_options()) {
|
||||
if (options.Is<T>()) {
|
||||
options.UnpackTo(result);
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ bool IsLengthDelimited(WireFormatLite::WireType wire_type) {
|
||||
}
|
||||
|
||||
// Reads a single data value for a wire type.
|
||||
::mediapipe::Status ReadFieldValue(uint32 tag, CodedInputStream* in,
|
||||
std::string* result) {
|
||||
mediapipe::Status ReadFieldValue(uint32 tag, CodedInputStream* in,
|
||||
std::string* result) {
|
||||
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
|
||||
if (IsLengthDelimited(wire_type)) {
|
||||
uint32 length;
|
||||
@@ -59,13 +59,13 @@ bool IsLengthDelimited(WireFormatLite::WireType wire_type) {
|
||||
cos.Trim();
|
||||
result->assign(field_data, tag_size, std::string::npos);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Reads the packed sequence of data values for a wire type.
|
||||
::mediapipe::Status ReadPackedValues(WireFormatLite::WireType wire_type,
|
||||
CodedInputStream* in,
|
||||
std::vector<std::string>* field_values) {
|
||||
mediapipe::Status ReadPackedValues(WireFormatLite::WireType wire_type,
|
||||
CodedInputStream* in,
|
||||
std::vector<std::string>* field_values) {
|
||||
uint32 data_size;
|
||||
RET_CHECK(in->ReadVarint32(&data_size));
|
||||
// fake_tag encodes the wire-type for calls to WireFormatLite::SkipField.
|
||||
@@ -77,15 +77,15 @@ bool IsLengthDelimited(WireFormatLite::WireType wire_type) {
|
||||
field_values->push_back(number);
|
||||
data_size -= number.size();
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Extracts the data value(s) for one field from a serialized message.
|
||||
// The message with these field values removed is written to |out|.
|
||||
::mediapipe::Status GetFieldValues(uint32 field_id,
|
||||
WireFormatLite::WireType wire_type,
|
||||
CodedInputStream* in, CodedOutputStream* out,
|
||||
std::vector<std::string>* field_values) {
|
||||
mediapipe::Status GetFieldValues(uint32 field_id,
|
||||
WireFormatLite::WireType wire_type,
|
||||
CodedInputStream* in, CodedOutputStream* out,
|
||||
std::vector<std::string>* field_values) {
|
||||
uint32 tag;
|
||||
while ((tag = in->ReadTag()) != 0) {
|
||||
int field_number = WireFormatLite::GetTagFieldNumber(tag);
|
||||
@@ -102,7 +102,7 @@ bool IsLengthDelimited(WireFormatLite::WireType wire_type) {
|
||||
RET_CHECK(WireFormatLite::SkipField(in, tag, out));
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Injects the data value(s) for one field into a serialized message.
|
||||
@@ -122,7 +122,7 @@ void SetFieldValues(uint32 field_id, WireFormatLite::WireType wire_type,
|
||||
FieldAccess::FieldAccess(uint32 field_id, FieldType field_type)
|
||||
: field_id_(field_id), field_type_(field_type) {}
|
||||
|
||||
::mediapipe::Status FieldAccess::SetMessage(const std::string& message) {
|
||||
mediapipe::Status FieldAccess::SetMessage(const std::string& message) {
|
||||
ArrayInputStream ais(message.data(), message.size());
|
||||
CodedInputStream in(&ais);
|
||||
StringOutputStream sos(&message_);
|
||||
@@ -146,7 +146,7 @@ std::vector<FieldValue>* FieldAccess::mutable_field_values() {
|
||||
}
|
||||
|
||||
// Replaces a range of field values for one field nested within a protobuf.
|
||||
::mediapipe::Status ProtoUtilLite::ReplaceFieldRange(
|
||||
mediapipe::Status ProtoUtilLite::ReplaceFieldRange(
|
||||
FieldValue* message, ProtoPath proto_path, int length, FieldType field_type,
|
||||
const std::vector<FieldValue>& field_values) {
|
||||
int field_id, index;
|
||||
@@ -169,11 +169,11 @@ std::vector<FieldValue>* FieldAccess::mutable_field_values() {
|
||||
}
|
||||
message->clear();
|
||||
access.GetMessage(message);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Returns a range of field values from one field nested within a protobuf.
|
||||
::mediapipe::Status ProtoUtilLite::GetFieldRange(
|
||||
mediapipe::Status ProtoUtilLite::GetFieldRange(
|
||||
const FieldValue& message, ProtoPath proto_path, int length,
|
||||
FieldType field_type, std::vector<FieldValue>* field_values) {
|
||||
int field_id, index;
|
||||
@@ -194,41 +194,40 @@ std::vector<FieldValue>* FieldAccess::mutable_field_values() {
|
||||
field_values->insert(field_values->begin(), v.begin() + index,
|
||||
v.begin() + index + length);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// If ok, returns OkStatus, otherwise returns InvalidArgumentError.
|
||||
template <typename T>
|
||||
::mediapipe::Status SyntaxStatus(bool ok, const std::string& text, T* result) {
|
||||
return ok ? ::mediapipe::OkStatus()
|
||||
: ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
mediapipe::Status SyntaxStatus(bool ok, const std::string& text, T* result) {
|
||||
return ok ? mediapipe::OkStatus()
|
||||
: mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Syntax error: \"", text, "\"",
|
||||
" for type: ", MediaPipeTypeStringOrDemangled<T>(), "."));
|
||||
}
|
||||
|
||||
// Templated parsing of a std::string value.
|
||||
template <typename T>
|
||||
::mediapipe::Status ParseValue(const std::string& text, T* result) {
|
||||
mediapipe::Status ParseValue(const std::string& text, T* result) {
|
||||
return SyntaxStatus(absl::SimpleAtoi(text, result), text, result);
|
||||
}
|
||||
template <>
|
||||
::mediapipe::Status ParseValue<double>(const std::string& text,
|
||||
double* result) {
|
||||
mediapipe::Status ParseValue<double>(const std::string& text, double* result) {
|
||||
return SyntaxStatus(absl::SimpleAtod(text, result), text, result);
|
||||
}
|
||||
template <>
|
||||
::mediapipe::Status ParseValue<float>(const std::string& text, float* result) {
|
||||
mediapipe::Status ParseValue<float>(const std::string& text, float* result) {
|
||||
return SyntaxStatus(absl::SimpleAtof(text, result), text, result);
|
||||
}
|
||||
template <>
|
||||
::mediapipe::Status ParseValue<bool>(const std::string& text, bool* result) {
|
||||
mediapipe::Status ParseValue<bool>(const std::string& text, bool* result) {
|
||||
return SyntaxStatus(absl::SimpleAtob(text, result), text, result);
|
||||
}
|
||||
template <>
|
||||
::mediapipe::Status ParseValue<std::string>(const std::string& text,
|
||||
std::string* result) {
|
||||
mediapipe::Status ParseValue<std::string>(const std::string& text,
|
||||
std::string* result) {
|
||||
*result = text;
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Templated formatting of a primitive value.
|
||||
@@ -239,20 +238,20 @@ std::string FormatValue(T v) {
|
||||
|
||||
// A helper function to parse and serialize one primtive value.
|
||||
template <typename T>
|
||||
::mediapipe::Status WritePrimitive(
|
||||
mediapipe::Status WritePrimitive(
|
||||
void (*writer)(T, proto_ns::io::CodedOutputStream*),
|
||||
const std::string& text, CodedOutputStream* out) {
|
||||
T value;
|
||||
MP_RETURN_IF_ERROR(ParseValue<T>(text, &value));
|
||||
(*writer)(value, out);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Serializes a protobuf FieldValue.
|
||||
static ::mediapipe::Status SerializeValue(const std::string& text,
|
||||
FieldType field_type,
|
||||
FieldValue* field_value) {
|
||||
::mediapipe::Status status;
|
||||
static mediapipe::Status SerializeValue(const std::string& text,
|
||||
FieldType field_type,
|
||||
FieldValue* field_value) {
|
||||
mediapipe::Status status;
|
||||
StringOutputStream sos(field_value);
|
||||
CodedOutputStream out(&sos);
|
||||
|
||||
@@ -278,11 +277,11 @@ static ::mediapipe::Status SerializeValue(const std::string& text,
|
||||
case W::TYPE_BYTES:
|
||||
case W::TYPE_STRING: {
|
||||
out.WriteRaw(text.data(), text.size());
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
case W::TYPE_GROUP:
|
||||
case W::TYPE_MESSAGE:
|
||||
return ::mediapipe::UnimplementedError(
|
||||
return mediapipe::UnimplementedError(
|
||||
"SerializeValue cannot serialize a Message.");
|
||||
case W::TYPE_UINT32:
|
||||
return WritePrimitive(W::WriteUInt32NoTag, text, &out);
|
||||
@@ -297,27 +296,27 @@ static ::mediapipe::Status SerializeValue(const std::string& text,
|
||||
case W::TYPE_SINT64:
|
||||
return WritePrimitive(W::WriteSInt64NoTag, text, &out);
|
||||
}
|
||||
return ::mediapipe::UnimplementedError("SerializeValue unimplemented type.");
|
||||
return mediapipe::UnimplementedError("SerializeValue unimplemented type.");
|
||||
}
|
||||
|
||||
// A helper function for deserializing one text value.
|
||||
template <typename CType, FieldType DeclaredType>
|
||||
static ::mediapipe::Status ReadPrimitive(CodedInputStream* input,
|
||||
std::string* result) {
|
||||
static mediapipe::Status ReadPrimitive(CodedInputStream* input,
|
||||
std::string* result) {
|
||||
CType value;
|
||||
if (!WireFormatLite::ReadPrimitive<CType, DeclaredType>(input, &value)) {
|
||||
return ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
return mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Bad serialized value: ", MediaPipeTypeStringOrDemangled<CType>(),
|
||||
"."));
|
||||
}
|
||||
*result = FormatValue(value);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Deserializes a protobuf FieldValue.
|
||||
static ::mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
FieldType field_type,
|
||||
std::string* result) {
|
||||
static mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
FieldType field_type,
|
||||
std::string* result) {
|
||||
ArrayInputStream ais(bytes.data(), bytes.size());
|
||||
CodedInputStream input(&ais);
|
||||
typedef WireFormatLite W;
|
||||
@@ -341,7 +340,7 @@ static ::mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
case W::TYPE_BYTES:
|
||||
case W::TYPE_STRING: {
|
||||
*result = bytes;
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
case W::TYPE_GROUP:
|
||||
case W::TYPE_MESSAGE:
|
||||
@@ -359,11 +358,10 @@ static ::mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
case W::TYPE_SINT64:
|
||||
return ReadPrimitive<proto_int64, W::TYPE_SINT64>(&input, result);
|
||||
}
|
||||
return ::mediapipe::UnimplementedError(
|
||||
"DeserializeValue unimplemented type.");
|
||||
return mediapipe::UnimplementedError("DeserializeValue unimplemented type.");
|
||||
}
|
||||
|
||||
::mediapipe::Status ProtoUtilLite::Serialize(
|
||||
mediapipe::Status ProtoUtilLite::Serialize(
|
||||
const std::vector<std::string>& text_values, FieldType field_type,
|
||||
std::vector<FieldValue>* result) {
|
||||
result->clear();
|
||||
@@ -373,10 +371,10 @@ static ::mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
MP_RETURN_IF_ERROR(SerializeValue(text_value, field_type, &field_value));
|
||||
result->push_back(field_value);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ProtoUtilLite::Deserialize(
|
||||
mediapipe::Status ProtoUtilLite::Deserialize(
|
||||
const std::vector<FieldValue>& field_values, FieldType field_type,
|
||||
std::vector<std::string>* result) {
|
||||
result->clear();
|
||||
@@ -386,7 +384,7 @@ static ::mediapipe::Status DeserializeValue(const FieldValue& bytes,
|
||||
MP_RETURN_IF_ERROR(DeserializeValue(field_value, field_type, &text_value));
|
||||
result->push_back(text_value);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
|
||||
@@ -47,7 +47,7 @@ class ProtoUtilLite {
|
||||
FieldAccess(uint32 field_id, FieldType field_type);
|
||||
|
||||
// Specifies the original serialized protobuf message.
|
||||
::mediapipe::Status SetMessage(const FieldValue& message);
|
||||
mediapipe::Status SetMessage(const FieldValue& message);
|
||||
|
||||
// Returns the serialized protobuf message with updated field values.
|
||||
void GetMessage(FieldValue* result);
|
||||
@@ -64,23 +64,24 @@ class ProtoUtilLite {
|
||||
|
||||
// Replace a range of field values nested within a protobuf.
|
||||
// Starting at the proto_path index, "length" values are replaced.
|
||||
static ::mediapipe::Status ReplaceFieldRange(
|
||||
static mediapipe::Status ReplaceFieldRange(
|
||||
FieldValue* message, ProtoPath proto_path, int length,
|
||||
FieldType field_type, const std::vector<FieldValue>& field_values);
|
||||
|
||||
// Retrieve a range of field values nested within a protobuf.
|
||||
// Starting at the proto_path index, "length" values are retrieved.
|
||||
static ::mediapipe::Status GetFieldRange(
|
||||
const FieldValue& message, ProtoPath proto_path, int length,
|
||||
FieldType field_type, std::vector<FieldValue>* field_values);
|
||||
static mediapipe::Status GetFieldRange(const FieldValue& message,
|
||||
ProtoPath proto_path, int length,
|
||||
FieldType field_type,
|
||||
std::vector<FieldValue>* field_values);
|
||||
|
||||
// Serialize one or more protobuf field values from text.
|
||||
static ::mediapipe::Status Serialize(
|
||||
static mediapipe::Status Serialize(
|
||||
const std::vector<std::string>& text_values, FieldType field_type,
|
||||
std::vector<FieldValue>* result);
|
||||
|
||||
// Deserialize one or more protobuf field values to text.
|
||||
static ::mediapipe::Status Deserialize(
|
||||
static mediapipe::Status Deserialize(
|
||||
const std::vector<FieldValue>& field_values, FieldType field_type,
|
||||
std::vector<std::string>* result);
|
||||
};
|
||||
|
||||
@@ -96,7 +96,7 @@ class SimulationClockTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
// Initialize the test clock as a RealClock.
|
||||
void SetupRealClock() { clock_ = ::mediapipe::Clock::RealClock(); }
|
||||
void SetupRealClock() { clock_ = mediapipe::Clock::RealClock(); }
|
||||
|
||||
// Return the values of the timestamps of a vector of Packets.
|
||||
static std::vector<int64> TimestampValues(
|
||||
@@ -119,7 +119,7 @@ class SimulationClockTest : public ::testing::Test {
|
||||
std::shared_ptr<SimulationClock> simulation_clock_;
|
||||
CalculatorGraphConfig graph_config_;
|
||||
CalculatorGraph graph_;
|
||||
::mediapipe::Clock* clock_;
|
||||
mediapipe::Clock* clock_;
|
||||
};
|
||||
|
||||
// Just directly calls SimulationClock::Sleep on several threads.
|
||||
@@ -177,19 +177,19 @@ TEST_F(SimulationClockTest, DuplicateWakeTimes) {
|
||||
}
|
||||
|
||||
// A Calculator::Process callback function.
|
||||
typedef std::function<::mediapipe::Status(const InputStreamShardSet&,
|
||||
OutputStreamShardSet*)>
|
||||
typedef std::function<mediapipe::Status(const InputStreamShardSet&,
|
||||
OutputStreamShardSet*)>
|
||||
ProcessFunction;
|
||||
|
||||
// A testing callback function that passes through all packets.
|
||||
::mediapipe::Status PassThrough(const InputStreamShardSet& inputs,
|
||||
OutputStreamShardSet* outputs) {
|
||||
mediapipe::Status PassThrough(const InputStreamShardSet& inputs,
|
||||
OutputStreamShardSet* outputs) {
|
||||
for (int i = 0; i < inputs.NumEntries(); ++i) {
|
||||
if (!inputs.Index(i).Value().IsEmpty()) {
|
||||
outputs->Index(i).AddPacket(inputs.Index(i).Value());
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// This test shows sim clock synchronizing a bunch of parallel tasks.
|
||||
|
||||
@@ -45,22 +45,22 @@ namespace {
|
||||
class MediaPipeInternalSidePacketToPacketStreamCalculator
|
||||
: public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->InputSidePackets().Index(0).SetAny();
|
||||
cc->Outputs().Index(0).SetSameAs(&cc->InputSidePackets().Index(0));
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) final {
|
||||
mediapipe::Status Open(CalculatorContext* cc) final {
|
||||
cc->Outputs().Index(0).AddPacket(
|
||||
cc->InputSidePackets().Index(0).At(Timestamp::PostStream()));
|
||||
cc->Outputs().Index(0).Close();
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
// The framework treats this calculator as a source calculator.
|
||||
return ::mediapipe::tool::StatusStop();
|
||||
return mediapipe::tool::StatusStop();
|
||||
}
|
||||
};
|
||||
REGISTER_CALCULATOR(MediaPipeInternalSidePacketToPacketStreamCalculator);
|
||||
@@ -222,7 +222,7 @@ void AddCallbackWithHeaderCalculator(const std::string& stream_name,
|
||||
// CallbackCalculator
|
||||
|
||||
// static
|
||||
::mediapipe::Status CallbackCalculator::GetContract(CalculatorContract* cc) {
|
||||
mediapipe::Status CallbackCalculator::GetContract(CalculatorContract* cc) {
|
||||
bool allow_multiple_streams = false;
|
||||
// If the input side packet is specified using tag "CALLBACK" it must contain
|
||||
// a std::function, which may be generated by CallbackPacketCalculator.
|
||||
@@ -237,7 +237,7 @@ void AddCallbackWithHeaderCalculator(const std::string& stream_name,
|
||||
.Set<std::function<void(const std::vector<Packet>&)>>();
|
||||
allow_multiple_streams = true;
|
||||
} else {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "InputSidePackets must use tags.";
|
||||
}
|
||||
|
||||
@@ -246,10 +246,10 @@ void AddCallbackWithHeaderCalculator(const std::string& stream_name,
|
||||
cc->Inputs().Index(i).SetAny();
|
||||
}
|
||||
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status CallbackCalculator::Open(CalculatorContext* cc) {
|
||||
mediapipe::Status CallbackCalculator::Open(CalculatorContext* cc) {
|
||||
if (cc->InputSidePackets().HasTag("CALLBACK")) {
|
||||
callback_ = cc->InputSidePackets()
|
||||
.Tag("CALLBACK")
|
||||
@@ -263,13 +263,13 @@ void AddCallbackWithHeaderCalculator(const std::string& stream_name,
|
||||
LOG(FATAL) << "InputSidePackets must use tags.";
|
||||
}
|
||||
if (callback_ == nullptr && vector_callback_ == nullptr) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "missing callback.";
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status CallbackCalculator::Process(CalculatorContext* cc) {
|
||||
mediapipe::Status CallbackCalculator::Process(CalculatorContext* cc) {
|
||||
if (callback_) {
|
||||
callback_(cc->Inputs().Index(0).Value());
|
||||
} else if (vector_callback_) {
|
||||
@@ -281,7 +281,7 @@ void AddCallbackWithHeaderCalculator(const std::string& stream_name,
|
||||
}
|
||||
vector_callback_(packets);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
REGISTER_CALCULATOR(CallbackCalculator);
|
||||
@@ -289,7 +289,7 @@ REGISTER_CALCULATOR(CallbackCalculator);
|
||||
// CallbackWithHeaderCalculator
|
||||
|
||||
// static
|
||||
::mediapipe::Status CallbackWithHeaderCalculator::GetContract(
|
||||
mediapipe::Status CallbackWithHeaderCalculator::GetContract(
|
||||
CalculatorContract* cc) {
|
||||
cc->Inputs().Tag("INPUT").SetAny();
|
||||
cc->Inputs().Tag("HEADER").SetAny();
|
||||
@@ -300,13 +300,13 @@ REGISTER_CALCULATOR(CallbackCalculator);
|
||||
.Tag("CALLBACK")
|
||||
.Set<std::function<void(const Packet&, const Packet&)>>();
|
||||
} else {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "InputSidePackets must use tags.";
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status CallbackWithHeaderCalculator::Open(CalculatorContext* cc) {
|
||||
mediapipe::Status CallbackWithHeaderCalculator::Open(CalculatorContext* cc) {
|
||||
if (cc->InputSidePackets().UsesTags()) {
|
||||
callback_ = cc->InputSidePackets()
|
||||
.Tag("CALLBACK")
|
||||
@@ -315,17 +315,17 @@ REGISTER_CALCULATOR(CallbackCalculator);
|
||||
LOG(FATAL) << "InputSidePackets must use tags.";
|
||||
}
|
||||
if (callback_ == nullptr) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "callback is nullptr.";
|
||||
}
|
||||
if (!cc->Inputs().HasTag("INPUT")) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "No input stream connected.";
|
||||
}
|
||||
if (!cc->Inputs().HasTag("HEADER")) {
|
||||
// Note: for the current MediaPipe header implementation, we just need to
|
||||
// connect the output stream to both of the two inputs: INPUT and HEADER.
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "No header stream connected.";
|
||||
}
|
||||
// If the input stream has the header, just use it as the header. Otherwise,
|
||||
@@ -333,16 +333,15 @@ REGISTER_CALCULATOR(CallbackCalculator);
|
||||
if (!cc->Inputs().Tag("INPUT").Header().IsEmpty()) {
|
||||
header_packet_ = cc->Inputs().Tag("INPUT").Header();
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status CallbackWithHeaderCalculator::Process(
|
||||
CalculatorContext* cc) {
|
||||
mediapipe::Status CallbackWithHeaderCalculator::Process(CalculatorContext* cc) {
|
||||
if (!cc->Inputs().Tag("INPUT").Value().IsEmpty() &&
|
||||
header_packet_.IsEmpty()) {
|
||||
// Header packet should be available before we receive any normal input
|
||||
// stream packet.
|
||||
return ::mediapipe::UnknownErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::UnknownErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Header not available!";
|
||||
}
|
||||
if (header_packet_.IsEmpty() &&
|
||||
@@ -352,7 +351,7 @@ REGISTER_CALCULATOR(CallbackCalculator);
|
||||
if (!cc->Inputs().Tag("INPUT").Value().IsEmpty()) {
|
||||
callback_(cc->Inputs().Tag("INPUT").Value(), header_packet_);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
REGISTER_CALCULATOR(CallbackWithHeaderCalculator);
|
||||
|
||||
@@ -166,10 +166,10 @@ class CallbackCalculator : public CalculatorBase {
|
||||
|
||||
~CallbackCalculator() override {}
|
||||
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
::mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
std::function<void(const Packet&)> callback_;
|
||||
@@ -185,10 +185,10 @@ class CallbackWithHeaderCalculator : public CalculatorBase {
|
||||
|
||||
~CallbackWithHeaderCalculator() override {}
|
||||
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
::mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
std::function<void(const Packet&, const Packet&)> callback_;
|
||||
|
||||
@@ -31,21 +31,21 @@ namespace mediapipe {
|
||||
namespace {
|
||||
class CountAndOutputSummarySidePacketInCloseCalculator : public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->Inputs().Index(0).SetAny();
|
||||
cc->OutputSidePackets().Index(0).Set<int>();
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
++count_;
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Close(CalculatorContext* cc) final {
|
||||
mediapipe::Status Close(CalculatorContext* cc) final {
|
||||
cc->OutputSidePackets().Index(0).Set(
|
||||
MakePacket<int>(count_).At(Timestamp::Unset()));
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
int count_ = 0;
|
||||
@@ -75,7 +75,7 @@ TEST(CallbackFromGeneratorTest, TestAddVectorSink) {
|
||||
|
||||
TEST(CalculatorGraph, OutputSummarySidePacketInClose) {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input_packets"
|
||||
node {
|
||||
calculator: "CountAndOutputSummarySidePacketInCloseCalculator"
|
||||
|
||||
@@ -43,19 +43,19 @@ class SidePacketsToStreamsCalculator : public CalculatorBase {
|
||||
const SidePacketsToStreamsCalculator&) = delete;
|
||||
~SidePacketsToStreamsCalculator() override {}
|
||||
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
auto& options = cc->Options<SidePacketsToStreamsCalculatorOptions>();
|
||||
if (options.has_num_inputs() &&
|
||||
(options.num_inputs() != cc->InputSidePackets().NumEntries() ||
|
||||
options.num_inputs() != cc->Outputs().NumEntries())) {
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"If num_inputs is specified it must be equal to the number of "
|
||||
"input side packets and output streams.");
|
||||
}
|
||||
if (!options.vectors_of_packets() &&
|
||||
options.set_timestamp() ==
|
||||
SidePacketsToStreamsCalculatorOptions::NONE) {
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"If set_timestamp is NONE, vectors_of_packets must not be false.");
|
||||
}
|
||||
for (int i = 0; i < cc->InputSidePackets().NumEntries(); ++i) {
|
||||
@@ -72,10 +72,10 @@ class SidePacketsToStreamsCalculator : public CalculatorBase {
|
||||
cc->Outputs().Index(i).SetSameAs(&cc->InputSidePackets().Index(i));
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
const auto& options = cc->Options<SidePacketsToStreamsCalculatorOptions>();
|
||||
// The i-th input side packet contains a vector of packets corresponding
|
||||
// to the values of this input for all batch elements.
|
||||
@@ -87,7 +87,7 @@ class SidePacketsToStreamsCalculator : public CalculatorBase {
|
||||
const auto& packets = input_side_packet.Get<std::vector<Packet>>();
|
||||
if (batch_size >= 0) {
|
||||
if (packets.size() != batch_size) {
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"The specified input side packets contain vectors of different "
|
||||
"sizes.");
|
||||
}
|
||||
|
||||
@@ -22,47 +22,46 @@
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
::mediapipe::Status StatusInvalid(const std::string& message) {
|
||||
return ::mediapipe::Status(::mediapipe::StatusCode::kInvalidArgument,
|
||||
message);
|
||||
mediapipe::Status StatusInvalid(const std::string& message) {
|
||||
return mediapipe::Status(mediapipe::StatusCode::kInvalidArgument, message);
|
||||
}
|
||||
|
||||
::mediapipe::Status StatusFail(const std::string& message) {
|
||||
return ::mediapipe::Status(::mediapipe::StatusCode::kUnknown, message);
|
||||
mediapipe::Status StatusFail(const std::string& message) {
|
||||
return mediapipe::Status(mediapipe::StatusCode::kUnknown, message);
|
||||
}
|
||||
|
||||
::mediapipe::Status StatusStop() {
|
||||
return ::mediapipe::Status(::mediapipe::StatusCode::kOutOfRange,
|
||||
"::mediapipe::tool::StatusStop()");
|
||||
mediapipe::Status StatusStop() {
|
||||
return mediapipe::Status(mediapipe::StatusCode::kOutOfRange,
|
||||
"mediapipe::tool::StatusStop()");
|
||||
}
|
||||
|
||||
::mediapipe::Status AddStatusPrefix(const std::string& prefix,
|
||||
const ::mediapipe::Status& status) {
|
||||
return ::mediapipe::Status(status.code(),
|
||||
absl::StrCat(prefix, status.message()));
|
||||
mediapipe::Status AddStatusPrefix(const std::string& prefix,
|
||||
const mediapipe::Status& status) {
|
||||
return mediapipe::Status(status.code(),
|
||||
absl::StrCat(prefix, status.message()));
|
||||
}
|
||||
|
||||
::mediapipe::Status CombinedStatus(
|
||||
mediapipe::Status CombinedStatus(
|
||||
const std::string& general_comment,
|
||||
const std::vector<::mediapipe::Status>& statuses) {
|
||||
// The final error code is ::mediapipe::StatusCode::kUnknown if not all
|
||||
const std::vector<mediapipe::Status>& statuses) {
|
||||
// The final error code is mediapipe::StatusCode::kUnknown if not all
|
||||
// the error codes are the same. Otherwise it is the same error code
|
||||
// as all of the (non-OK) statuses. If statuses is empty or they are
|
||||
// all OK, then ::mediapipe::OkStatus() is returned.
|
||||
::mediapipe::StatusCode error_code = ::mediapipe::StatusCode::kOk;
|
||||
// all OK, then mediapipe::OkStatus() is returned.
|
||||
mediapipe::StatusCode error_code = mediapipe::StatusCode::kOk;
|
||||
std::vector<std::string> errors;
|
||||
for (const ::mediapipe::Status& status : statuses) {
|
||||
for (const mediapipe::Status& status : statuses) {
|
||||
if (!status.ok()) {
|
||||
errors.emplace_back(status.message());
|
||||
if (error_code == ::mediapipe::StatusCode::kOk) {
|
||||
if (error_code == mediapipe::StatusCode::kOk) {
|
||||
error_code = status.code();
|
||||
} else if (error_code != status.code()) {
|
||||
error_code = ::mediapipe::StatusCode::kUnknown;
|
||||
error_code = mediapipe::StatusCode::kUnknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error_code == StatusCode::kOk) return OkStatus();
|
||||
Status combined = ::mediapipe::Status(
|
||||
Status combined = mediapipe::Status(
|
||||
error_code,
|
||||
absl::StrCat(general_comment, "\n", absl::StrJoin(errors, "\n")));
|
||||
return combined;
|
||||
|
||||
@@ -29,31 +29,31 @@ namespace tool {
|
||||
// be called on it again). When returned from a non-source Calculator
|
||||
// it signals that the graph should be cancelled (which is handled by
|
||||
// closing all source Calculators and waiting for the graph to finish).
|
||||
::mediapipe::Status StatusStop();
|
||||
mediapipe::Status StatusStop();
|
||||
|
||||
// Return a status which signals an invalid initial condition (for
|
||||
// example an InputSidePacket does not include all necessary fields).
|
||||
ABSL_DEPRECATED("Use ::mediapipe::InvalidArgumentError(error_message) instead.")
|
||||
::mediapipe::Status StatusInvalid(const std::string& error_message);
|
||||
ABSL_DEPRECATED("Use mediapipe::InvalidArgumentError(error_message) instead.")
|
||||
mediapipe::Status StatusInvalid(const std::string& error_message);
|
||||
|
||||
// Return a status which signals that something unexpectedly failed.
|
||||
ABSL_DEPRECATED("Use ::mediapipe::UnknownError(error_message) instead.")
|
||||
::mediapipe::Status StatusFail(const std::string& error_message);
|
||||
ABSL_DEPRECATED("Use mediapipe::UnknownError(error_message) instead.")
|
||||
mediapipe::Status StatusFail(const std::string& error_message);
|
||||
|
||||
// Prefixes the given std::string to the error message in status.
|
||||
// This function should be considered internal to the framework.
|
||||
// TODO Replace usage of AddStatusPrefix with util::Annotate().
|
||||
::mediapipe::Status AddStatusPrefix(const std::string& prefix,
|
||||
const ::mediapipe::Status& status);
|
||||
mediapipe::Status AddStatusPrefix(const std::string& prefix,
|
||||
const mediapipe::Status& status);
|
||||
|
||||
// Combine a vector of ::mediapipe::Status into a single composite status.
|
||||
// If statuses is empty or all statuses are OK then ::mediapipe::OkStatus()
|
||||
// Combine a vector of mediapipe::Status into a single composite status.
|
||||
// If statuses is empty or all statuses are OK then mediapipe::OkStatus()
|
||||
// will be returned.
|
||||
// This function should be considered internal to the framework.
|
||||
// TODO Move this function to somewhere with less visibility.
|
||||
::mediapipe::Status CombinedStatus(
|
||||
mediapipe::Status CombinedStatus(
|
||||
const std::string& general_comment,
|
||||
const std::vector<::mediapipe::Status>& statuses);
|
||||
const std::vector<mediapipe::Status>& statuses);
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -36,24 +36,24 @@ TEST(StatusTest, StatusStopIsNotOk) { EXPECT_FALSE(tool::StatusStop().ok()); }
|
||||
TEST(StatusTest, Prefix) {
|
||||
const std::string base_error_message("error_with_this_string");
|
||||
const std::string prefix_error_message("error_with_prefix: ");
|
||||
::mediapipe::Status base_status = ::mediapipe::Status(
|
||||
::mediapipe::StatusCode::kInvalidArgument, base_error_message);
|
||||
::mediapipe::Status status =
|
||||
mediapipe::Status base_status = mediapipe::Status(
|
||||
mediapipe::StatusCode::kInvalidArgument, base_error_message);
|
||||
mediapipe::Status status =
|
||||
tool::AddStatusPrefix(prefix_error_message, base_status);
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(base_error_message));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(prefix_error_message));
|
||||
EXPECT_EQ(::mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
EXPECT_EQ(mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
}
|
||||
|
||||
TEST(StatusTest, CombinedStatus) {
|
||||
std::vector<::mediapipe::Status> errors;
|
||||
std::vector<mediapipe::Status> errors;
|
||||
const std::string prefix_error_message("error_with_prefix: ");
|
||||
::mediapipe::Status status;
|
||||
mediapipe::Status status;
|
||||
|
||||
errors.clear();
|
||||
errors.emplace_back(::mediapipe::StatusCode::kInvalidArgument,
|
||||
errors.emplace_back(mediapipe::StatusCode::kInvalidArgument,
|
||||
"error_with_this_string");
|
||||
errors.emplace_back(::mediapipe::StatusCode::kInvalidArgument,
|
||||
errors.emplace_back(mediapipe::StatusCode::kInvalidArgument,
|
||||
"error_with_that_string");
|
||||
errors.back().SetPayload("test payload type",
|
||||
absl::Cord(absl::string_view("hello")));
|
||||
@@ -61,30 +61,30 @@ TEST(StatusTest, CombinedStatus) {
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(std::string(errors[0].message())));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(std::string(errors[1].message())));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(prefix_error_message));
|
||||
EXPECT_EQ(::mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
EXPECT_EQ(mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
|
||||
errors.clear();
|
||||
errors.emplace_back(::mediapipe::StatusCode::kNotFound,
|
||||
errors.emplace_back(mediapipe::StatusCode::kNotFound,
|
||||
"error_with_this_string");
|
||||
errors.emplace_back(::mediapipe::StatusCode::kInvalidArgument,
|
||||
errors.emplace_back(mediapipe::StatusCode::kInvalidArgument,
|
||||
"error_with_that_string");
|
||||
status = tool::CombinedStatus(prefix_error_message, errors);
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(std::string(errors[0].message())));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(std::string(errors[1].message())));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(prefix_error_message));
|
||||
EXPECT_EQ(::mediapipe::StatusCode::kUnknown, status.code());
|
||||
EXPECT_EQ(mediapipe::StatusCode::kUnknown, status.code());
|
||||
errors.clear();
|
||||
errors.emplace_back(::mediapipe::StatusCode::kOk, "error_with_this_string");
|
||||
errors.emplace_back(::mediapipe::StatusCode::kInvalidArgument,
|
||||
errors.emplace_back(mediapipe::StatusCode::kOk, "error_with_this_string");
|
||||
errors.emplace_back(mediapipe::StatusCode::kInvalidArgument,
|
||||
"error_with_that_string");
|
||||
status = tool::CombinedStatus(prefix_error_message, errors);
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(std::string(errors[1].message())));
|
||||
EXPECT_THAT(status.ToString(), HasSubstr(prefix_error_message));
|
||||
EXPECT_EQ(::mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
EXPECT_EQ(mediapipe::StatusCode::kInvalidArgument, status.code());
|
||||
|
||||
errors.clear();
|
||||
errors.emplace_back(::mediapipe::StatusCode::kOk, "error_with_this_string");
|
||||
errors.emplace_back(::mediapipe::StatusCode::kOk, "error_with_that_string");
|
||||
errors.emplace_back(mediapipe::StatusCode::kOk, "error_with_this_string");
|
||||
errors.emplace_back(mediapipe::StatusCode::kOk, "error_with_that_string");
|
||||
MP_EXPECT_OK(tool::CombinedStatus(prefix_error_message, errors));
|
||||
|
||||
errors.clear();
|
||||
@@ -93,13 +93,13 @@ TEST(StatusTest, CombinedStatus) {
|
||||
|
||||
// Verify tool::StatusInvalid() and tool::StatusFail() and the alternatives
|
||||
// recommended by their ABSL_DEPRECATED messages return the same
|
||||
// ::mediapipe::Status objects.
|
||||
// mediapipe::Status objects.
|
||||
TEST(StatusTest, Deprecated) {
|
||||
const std::string error_message = "an error message";
|
||||
EXPECT_EQ(tool::StatusInvalid(error_message), // NOLINT
|
||||
::mediapipe::InvalidArgumentError(error_message));
|
||||
mediapipe::InvalidArgumentError(error_message));
|
||||
EXPECT_EQ(tool::StatusFail(error_message), // NOLINT
|
||||
::mediapipe::UnknownError(error_message));
|
||||
mediapipe::UnknownError(error_message));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace mediapipe {
|
||||
|
||||
namespace tool {
|
||||
|
||||
::mediapipe::Status TransformStreamNames(
|
||||
mediapipe::Status TransformStreamNames(
|
||||
proto_ns::RepeatedPtrField<ProtoString>* streams,
|
||||
const std::function<std::string(absl::string_view)>& transform) {
|
||||
for (auto& stream : *streams) {
|
||||
@@ -53,11 +53,11 @@ namespace tool {
|
||||
absl::StrCat(port_and_name.substr(0, name_pos),
|
||||
transform(absl::ClippedSubstr(port_and_name, name_pos)));
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Returns subgraph streams not requested by a subgraph-node.
|
||||
::mediapipe::Status FindIgnoredStreams(
|
||||
mediapipe::Status FindIgnoredStreams(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& src_streams,
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& dst_streams,
|
||||
std::set<std::string>* result) {
|
||||
@@ -69,11 +69,11 @@ namespace tool {
|
||||
result->insert(src_map->Names()[id.value()]);
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Removes subgraph streams not requested by a subgraph-node.
|
||||
::mediapipe::Status RemoveIgnoredStreams(
|
||||
mediapipe::Status RemoveIgnoredStreams(
|
||||
proto_ns::RepeatedPtrField<ProtoString>* streams,
|
||||
const std::set<std::string>& missing_streams) {
|
||||
for (int i = streams->size() - 1; i >= 0; --i) {
|
||||
@@ -84,10 +84,10 @@ namespace tool {
|
||||
streams->DeleteSubrange(i, 1);
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status TransformNames(
|
||||
mediapipe::Status TransformNames(
|
||||
CalculatorGraphConfig* config,
|
||||
const std::function<std::string(absl::string_view)>& transform) {
|
||||
RET_CHECK_EQ(config->packet_factory().size(), 0);
|
||||
@@ -122,7 +122,7 @@ namespace tool {
|
||||
MP_RETURN_IF_ERROR(TransformStreamNames(
|
||||
status_handler.mutable_input_side_packet(), transform));
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Adds a prefix to the name of each stream, side packet and node in the
|
||||
@@ -131,8 +131,8 @@ namespace tool {
|
||||
// 2, { foo, bar } --PrefixNames-> { rsg__foo, rsg__bar }
|
||||
// This means that two copies of the same subgraph will not interfere with
|
||||
// each other.
|
||||
static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
CalculatorGraphConfig* config) {
|
||||
static mediapipe::Status PrefixNames(std::string prefix,
|
||||
CalculatorGraphConfig* config) {
|
||||
std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
|
||||
std::replace(prefix.begin(), prefix.end(), '.', '_');
|
||||
std::replace(prefix.begin(), prefix.end(), ' ', '_');
|
||||
@@ -144,7 +144,7 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
return TransformNames(config, add_prefix);
|
||||
}
|
||||
|
||||
::mediapipe::Status FindCorrespondingStreams(
|
||||
mediapipe::Status FindCorrespondingStreams(
|
||||
std::map<std::string, std::string>* stream_map,
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& src_streams,
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& dst_streams) {
|
||||
@@ -153,16 +153,16 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
for (const auto& it : dst_map->Mapping()) {
|
||||
const std::string& tag = it.first;
|
||||
const TagMap::TagData* src_tag_data =
|
||||
::mediapipe::FindOrNull(src_map->Mapping(), tag);
|
||||
mediapipe::FindOrNull(src_map->Mapping(), tag);
|
||||
if (!src_tag_data) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Tag \"" << tag << "\" does not exist in the subgraph config.";
|
||||
}
|
||||
const TagMap::TagData& dst_tag_data = it.second;
|
||||
CollectionItemId src_id = src_tag_data->id;
|
||||
CollectionItemId dst_id = dst_tag_data.id;
|
||||
if (dst_tag_data.count > src_tag_data->count) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Tag \"" << tag << "\" has " << dst_tag_data.count
|
||||
<< " indexes in the subgraph node but has only "
|
||||
<< src_tag_data->count << " indexes in the subgraph config.";
|
||||
@@ -175,28 +175,28 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
(*stream_map)[src_name] = dst_name;
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// The following fields can be used in a Node message for a subgraph:
|
||||
// name, calculator, input_stream, output_stream, input_side_packet,
|
||||
// output_side_packet, options.
|
||||
// All other fields are only applicable to calculators.
|
||||
::mediapipe::Status ValidateSubgraphFields(
|
||||
mediapipe::Status ValidateSubgraphFields(
|
||||
const CalculatorGraphConfig::Node& subgraph_node) {
|
||||
if (subgraph_node.source_layer() || subgraph_node.buffer_size_hint() ||
|
||||
subgraph_node.has_input_stream_handler() ||
|
||||
subgraph_node.has_output_stream_handler() ||
|
||||
subgraph_node.input_stream_info_size() != 0 ||
|
||||
!subgraph_node.executor().empty()) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Subgraph \"" << subgraph_node.name()
|
||||
<< "\" has a field that is only applicable to calculators.";
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ConnectSubgraphStreams(
|
||||
mediapipe::Status ConnectSubgraphStreams(
|
||||
const CalculatorGraphConfig::Node& subgraph_node,
|
||||
CalculatorGraphConfig* subgraph_config) {
|
||||
std::map<std::string, std::string> stream_map;
|
||||
@@ -237,7 +237,7 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
std::map<std::string, std::string>* name_map;
|
||||
auto replace_names = [&name_map](absl::string_view s) {
|
||||
std::string original(s);
|
||||
std::string* replacement = ::mediapipe::FindOrNull(*name_map, original);
|
||||
std::string* replacement = mediapipe::FindOrNull(*name_map, original);
|
||||
return replacement ? *replacement : original;
|
||||
};
|
||||
for (auto& node : *subgraph_config->mutable_node()) {
|
||||
@@ -269,11 +269,11 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
MP_RETURN_IF_ERROR(RemoveIgnoredStreams(
|
||||
generator.mutable_input_side_packet(), ignored_input_side_packets));
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ExpandSubgraphs(CalculatorGraphConfig* config,
|
||||
const GraphRegistry* graph_registry) {
|
||||
mediapipe::Status ExpandSubgraphs(CalculatorGraphConfig* config,
|
||||
const GraphRegistry* graph_registry) {
|
||||
graph_registry =
|
||||
graph_registry ? graph_registry : &GraphRegistry::global_graph_registry;
|
||||
RET_CHECK(config);
|
||||
@@ -313,7 +313,7 @@ static ::mediapipe::Status PrefixNames(std::string prefix,
|
||||
config->mutable_status_handler()));
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
CalculatorGraphConfig MakeSingleNodeGraph(CalculatorGraphConfig::Node node) {
|
||||
|
||||
@@ -29,13 +29,13 @@ namespace tool {
|
||||
|
||||
// Apply the given transformation function to the names of streams and
|
||||
// side packets.
|
||||
::mediapipe::Status TransformStreamNames(
|
||||
mediapipe::Status TransformStreamNames(
|
||||
proto_ns::RepeatedPtrField<ProtoString>* streams,
|
||||
const std::function<std::string(absl::string_view)>& transform);
|
||||
|
||||
// Apply the given transformation function to the names of streams,
|
||||
// side packets, and nodes.
|
||||
::mediapipe::Status TransformNames(
|
||||
mediapipe::Status TransformNames(
|
||||
CalculatorGraphConfig* config,
|
||||
const std::function<std::string(absl::string_view)>& transform);
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace tool {
|
||||
// src: FOO:abc dst: FOO:bob
|
||||
// BAR:def
|
||||
// The entry 'abc' -> 'bob' is added to the map.
|
||||
::mediapipe::Status FindCorrespondingStreams(
|
||||
mediapipe::Status FindCorrespondingStreams(
|
||||
std::map<std::string, std::string>* stream_map,
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& src_streams,
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& dst_streams);
|
||||
@@ -56,19 +56,19 @@ namespace tool {
|
||||
// Validates the fields in the given Node message that specifies a subgraph.
|
||||
// Returns an error status if the Node message contains any field that is only
|
||||
// applicable to calculators.
|
||||
::mediapipe::Status ValidateSubgraphFields(
|
||||
mediapipe::Status ValidateSubgraphFields(
|
||||
const CalculatorGraphConfig::Node& subgraph_node);
|
||||
|
||||
// Renames the streams in a subgraph config to match the connections on the
|
||||
// wrapping node.
|
||||
::mediapipe::Status ConnectSubgraphStreams(
|
||||
mediapipe::Status ConnectSubgraphStreams(
|
||||
const CalculatorGraphConfig::Node& subgraph_node,
|
||||
CalculatorGraphConfig* subgraph_config);
|
||||
|
||||
// Replaces subgraph nodes in the given config with the contents of the
|
||||
// corresponding subgraphs. Nested subgraphs are retrieved from the
|
||||
// graph registry and expanded recursively.
|
||||
::mediapipe::Status ExpandSubgraphs(
|
||||
mediapipe::Status ExpandSubgraphs(
|
||||
CalculatorGraphConfig* config,
|
||||
const GraphRegistry* graph_registry = nullptr);
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace {
|
||||
|
||||
class SimpleTestCalculator : public CalculatorBase {
|
||||
public:
|
||||
::mediapipe::Status Process(CalculatorContext* cc) override {
|
||||
return ::mediapipe::OkStatus();
|
||||
mediapipe::Status Process(CalculatorContext* cc) override {
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
for (PacketType& type : cc->Inputs()) {
|
||||
type.Set<int>();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class SimpleTestCalculator : public CalculatorBase {
|
||||
for (PacketType& type : cc->InputSidePackets()) {
|
||||
type.Set<int>();
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
};
|
||||
REGISTER_CALCULATOR(SimpleTestCalculator);
|
||||
@@ -66,10 +66,10 @@ REGISTER_CALCULATOR(SomeAggregator);
|
||||
|
||||
class TestSubgraph : public Subgraph {
|
||||
public:
|
||||
::mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const SubgraphOptions& /*options*/) override {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "DATA:input_1"
|
||||
node {
|
||||
name: "regular_node"
|
||||
@@ -95,10 +95,10 @@ REGISTER_MEDIAPIPE_GRAPH(TestSubgraph);
|
||||
|
||||
class PacketFactoryTestSubgraph : public Subgraph {
|
||||
public:
|
||||
::mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const SubgraphOptions& /*options*/) override {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "DATA:input_1"
|
||||
node {
|
||||
name: "regular_node"
|
||||
@@ -126,7 +126,7 @@ REGISTER_MEDIAPIPE_GRAPH(PacketFactoryTestSubgraph);
|
||||
// and the number of copies of the node are specified in subgraph options.
|
||||
class NodeChainSubgraph : public Subgraph {
|
||||
public:
|
||||
::mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const SubgraphOptions& options) override {
|
||||
auto opts =
|
||||
Subgraph::GetOptions<mediapipe::NodeChainSubgraphOptions>(options);
|
||||
@@ -152,10 +152,10 @@ REGISTER_MEDIAPIPE_GRAPH(NodeChainSubgraph);
|
||||
// subgraph contains a node with the executor field "custom_thread_pool".
|
||||
class NodeWithExecutorSubgraph : public Subgraph {
|
||||
public:
|
||||
::mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const SubgraphOptions& options) override {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "INPUT:foo"
|
||||
output_stream: "OUTPUT:bar"
|
||||
node {
|
||||
@@ -174,10 +174,10 @@ REGISTER_MEDIAPIPE_GRAPH(NodeWithExecutorSubgraph);
|
||||
// subgraph contains a NodeWithExecutorSubgraph.
|
||||
class EnclosingSubgraph : public Subgraph {
|
||||
public:
|
||||
::mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const SubgraphOptions& options) override {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "IN:in"
|
||||
output_stream: "OUT:out"
|
||||
node {
|
||||
@@ -193,7 +193,7 @@ REGISTER_MEDIAPIPE_GRAPH(EnclosingSubgraph);
|
||||
|
||||
TEST(SubgraphExpansionTest, TransformStreamNames) {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSinkCalculator"
|
||||
input_stream: "input_1"
|
||||
@@ -203,7 +203,7 @@ TEST(SubgraphExpansionTest, TransformStreamNames) {
|
||||
}
|
||||
)");
|
||||
CalculatorGraphConfig expected_config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSinkCalculator"
|
||||
input_stream: "input_1_foo"
|
||||
@@ -220,7 +220,7 @@ TEST(SubgraphExpansionTest, TransformStreamNames) {
|
||||
|
||||
TEST(SubgraphExpansionTest, TransformNames) {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input_1"
|
||||
node {
|
||||
calculator: "SomeRegularCalculator"
|
||||
@@ -238,7 +238,7 @@ TEST(SubgraphExpansionTest, TransformNames) {
|
||||
}
|
||||
)");
|
||||
CalculatorGraphConfig expected_config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "__sg0_input_1"
|
||||
node {
|
||||
calculator: "SomeRegularCalculator"
|
||||
@@ -265,14 +265,14 @@ TEST(SubgraphExpansionTest, TransformNames) {
|
||||
|
||||
TEST(SubgraphExpansionTest, FindCorrespondingStreams) {
|
||||
CalculatorGraphConfig config1 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input_1"
|
||||
input_stream: "VIDEO:input_2"
|
||||
input_stream: "AUDIO:0:input_3"
|
||||
input_stream: "AUDIO:1:input_4"
|
||||
)");
|
||||
CalculatorGraphConfig config2 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSubgraph"
|
||||
input_stream: "foo"
|
||||
@@ -294,13 +294,13 @@ TEST(SubgraphExpansionTest, FindCorrespondingStreams) {
|
||||
TEST(SubgraphExpansionTest, FindCorrespondingStreamsNonexistentTag) {
|
||||
// The VIDEO tag does not exist in the subgraph.
|
||||
CalculatorGraphConfig config1 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input_1"
|
||||
input_stream: "AUDIO:0:input_3"
|
||||
input_stream: "AUDIO:1:input_4"
|
||||
)");
|
||||
CalculatorGraphConfig config2 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSubgraph"
|
||||
input_stream: "foo"
|
||||
@@ -324,13 +324,13 @@ TEST(SubgraphExpansionTest, FindCorrespondingStreamsNonexistentTag) {
|
||||
TEST(SubgraphExpansionTest, FindCorrespondingStreamsTooFewIndexes) {
|
||||
// The AUDIO tag has too few indexes in the subgraph (1 vs. 2).
|
||||
CalculatorGraphConfig config1 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input_1"
|
||||
input_stream: "VIDEO:input_2"
|
||||
input_stream: "AUDIO:0:input_3"
|
||||
)");
|
||||
CalculatorGraphConfig config2 =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSubgraph"
|
||||
input_stream: "foo"
|
||||
@@ -353,7 +353,7 @@ TEST(SubgraphExpansionTest, FindCorrespondingStreamsTooFewIndexes) {
|
||||
|
||||
TEST(SubgraphExpansionTest, ConnectSubgraphStreams) {
|
||||
CalculatorGraphConfig subgraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "A:input_1"
|
||||
input_stream: "B:input_2"
|
||||
output_stream: "O:output_2"
|
||||
@@ -379,7 +379,7 @@ TEST(SubgraphExpansionTest, ConnectSubgraphStreams) {
|
||||
}
|
||||
)");
|
||||
CalculatorGraphConfig supergraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "SomeSubgraph"
|
||||
input_stream: "A:foo"
|
||||
@@ -392,7 +392,7 @@ TEST(SubgraphExpansionTest, ConnectSubgraphStreams) {
|
||||
// Note: graph input streams, output streams, and side packets on the
|
||||
// subgraph are not changed because they are going to be discarded anyway.
|
||||
CalculatorGraphConfig expected_subgraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "A:input_1"
|
||||
input_stream: "B:input_2"
|
||||
output_stream: "O:output_2"
|
||||
@@ -423,7 +423,7 @@ TEST(SubgraphExpansionTest, ConnectSubgraphStreams) {
|
||||
|
||||
TEST(SubgraphExpansionTest, ExpandSubgraphs) {
|
||||
CalculatorGraphConfig supergraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
name: "simple_source"
|
||||
calculator: "SomeSourceCalculator"
|
||||
@@ -432,7 +432,7 @@ TEST(SubgraphExpansionTest, ExpandSubgraphs) {
|
||||
node { calculator: "TestSubgraph" input_stream: "DATA:foo" }
|
||||
)");
|
||||
CalculatorGraphConfig expected_graph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
name: "simple_source"
|
||||
calculator: "SomeSourceCalculator"
|
||||
@@ -461,7 +461,7 @@ TEST(SubgraphExpansionTest, ExpandSubgraphs) {
|
||||
|
||||
TEST(SubgraphExpansionTest, ValidateSubgraphFields) {
|
||||
CalculatorGraphConfig supergraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
name: "simple_source"
|
||||
calculator: "SomeSourceCalculator"
|
||||
@@ -474,12 +474,12 @@ TEST(SubgraphExpansionTest, ValidateSubgraphFields) {
|
||||
buffer_size_hint: -1 # This field is only applicable to calculators.
|
||||
}
|
||||
)");
|
||||
::mediapipe::Status s1 = tool::ValidateSubgraphFields(supergraph.node(1));
|
||||
EXPECT_EQ(s1.code(), ::mediapipe::StatusCode::kInvalidArgument);
|
||||
mediapipe::Status s1 = tool::ValidateSubgraphFields(supergraph.node(1));
|
||||
EXPECT_EQ(s1.code(), mediapipe::StatusCode::kInvalidArgument);
|
||||
EXPECT_THAT(s1.message(), testing::HasSubstr("foo_subgraph"));
|
||||
|
||||
::mediapipe::Status s2 = tool::ExpandSubgraphs(&supergraph);
|
||||
EXPECT_EQ(s2.code(), ::mediapipe::StatusCode::kInvalidArgument);
|
||||
mediapipe::Status s2 = tool::ExpandSubgraphs(&supergraph);
|
||||
EXPECT_EQ(s2.code(), mediapipe::StatusCode::kInvalidArgument);
|
||||
EXPECT_THAT(s2.message(), testing::HasSubstr("foo_subgraph"));
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ TEST(SubgraphExpansionTest, ValidateSubgraphFields) {
|
||||
// subgraph executor support in the future.
|
||||
TEST(SubgraphExpansionTest, ExecutorFieldOfNodeInSubgraphPreserved) {
|
||||
CalculatorGraphConfig supergraph =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "input"
|
||||
executor {
|
||||
name: "custom_thread_pool"
|
||||
@@ -504,7 +504,7 @@ TEST(SubgraphExpansionTest, ExecutorFieldOfNodeInSubgraphPreserved) {
|
||||
output_stream: "OUT:output"
|
||||
}
|
||||
)");
|
||||
CalculatorGraphConfig expected_graph = ::mediapipe::ParseTextProtoOrDie<
|
||||
CalculatorGraphConfig expected_graph = mediapipe::ParseTextProtoOrDie<
|
||||
CalculatorGraphConfig>(R"(
|
||||
input_stream: "input"
|
||||
executor {
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "mediapipe/framework/calculator.pb.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/mediapipe_options.pb.h"
|
||||
#include "mediapipe/framework/port/canonical_errors.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/stream_handler.pb.h"
|
||||
#include "mediapipe/framework/stream_handler/sync_set_input_stream_handler.pb.h"
|
||||
#include "mediapipe/framework/tool/container_util.h"
|
||||
#include "mediapipe/framework/tool/name_util.h"
|
||||
#include "mediapipe/framework/tool/subgraph_expansion.h"
|
||||
#include "mediapipe/framework/tool/switch_container.pb.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
using mediapipe::SwitchContainerOptions;
|
||||
|
||||
// A graph factory producing a CalculatorGraphConfig routing packets to
|
||||
// one of several contained CalculatorGraphConfigs.
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// node {
|
||||
// calculator: "SwitchContainer"
|
||||
// input_stream: "ENABLE:enable"
|
||||
// input_stream: "INPUT_VIDEO:video_frames"
|
||||
// output_stream: "OUTPUT_VIDEO:output_frames"
|
||||
// options {
|
||||
// [mediapipe.SwitchContainerOptions.ext] {
|
||||
// contained_node: { calculator: "BasicSubgraph" }
|
||||
// contained_node: { calculator: "AdvancedSubgraph" }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Note that the input and output stream tags supplied to the container node
|
||||
// must match the input and output stream tags required by the contained nodes,
|
||||
// such as "INPUT_VIDEO" and "OUTPUT_VIDEO" in the example above.
|
||||
//
|
||||
// Input stream "ENABLE" specifies routing of packets to either contained_node 0
|
||||
// or contained_node 1, given "ENABLE:false" or "ENABLE:true" respectively.
|
||||
// Input-side-packet "ENABLE" and input-stream "SELECT" can also be used
|
||||
// similarly to specify the active channel.
|
||||
class SwitchContainer : public Subgraph {
|
||||
public:
|
||||
SwitchContainer() = default;
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
const Subgraph::SubgraphOptions& options) override;
|
||||
};
|
||||
REGISTER_MEDIAPIPE_GRAPH(SwitchContainer);
|
||||
|
||||
using TagIndex = std::pair<std::string, int>;
|
||||
|
||||
// Returns the stream name for one of the demux output channels.
|
||||
// This is the channel number followed by the stream name separated by "__".
|
||||
// For example, the channel-name for sream "frame" on channel 1 is "c1__frame".
|
||||
std::string ChannelName(const std::string& name, int channel) {
|
||||
return absl::StrCat("c", channel, "__", name);
|
||||
}
|
||||
|
||||
// Returns a SwitchDemuxCalculator node.
|
||||
CalculatorGraphConfig::Node* BuildDemuxNode(
|
||||
const std::map<TagIndex, std::string>& input_tags,
|
||||
CalculatorGraphConfig* config) {
|
||||
CalculatorGraphConfig::Node* result = config->add_node();
|
||||
*result->mutable_calculator() = "SwitchDemuxCalculator";
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a SwitchMuxCalculator node.
|
||||
CalculatorGraphConfig::Node* BuildMuxNode(
|
||||
const std::map<TagIndex, std::string>& output_tags,
|
||||
CalculatorGraphConfig* config) {
|
||||
CalculatorGraphConfig::Node* result = config->add_node();
|
||||
*result->mutable_calculator() = "SwitchMuxCalculator";
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns an unused name similar to a specified name.
|
||||
std::string UniqueName(std::string name, std::set<std::string>* names) {
|
||||
CHECK(names != nullptr);
|
||||
std::string result = name;
|
||||
int suffix = 2;
|
||||
while (names->count(result) > 0) {
|
||||
result = absl::StrCat(name, "_", suffix++);
|
||||
}
|
||||
names->insert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parses tag, index, and name from a list of stream identifiers.
|
||||
void ParseTags(const proto_ns::RepeatedPtrField<std::string>& streams,
|
||||
std::map<TagIndex, std::string>* result) {
|
||||
CHECK(result != nullptr);
|
||||
std::set<std::string> used_names;
|
||||
int used_index = -1;
|
||||
for (const std::string& stream : streams) {
|
||||
std::string name = UniqueName(ParseNameFromStream(stream), &used_names);
|
||||
TagIndex tag_index = ParseTagIndexFromStream(stream);
|
||||
if (tag_index.second == -1) {
|
||||
tag_index.second = ++used_index;
|
||||
}
|
||||
result->insert({tag_index, name});
|
||||
}
|
||||
}
|
||||
|
||||
// Removes the entry for a tag and index from a map.
|
||||
void EraseTag(const std::string& stream,
|
||||
std::map<TagIndex, std::string>* streams) {
|
||||
CHECK(streams != nullptr);
|
||||
streams->erase(ParseTagIndexFromStream(absl::StrCat(stream, ":u")));
|
||||
}
|
||||
|
||||
// Removes the entry for a tag and index from a list.
|
||||
void EraseTag(const std::string& stream,
|
||||
proto_ns::RepeatedPtrField<std::string>* streams) {
|
||||
CHECK(streams != nullptr);
|
||||
TagIndex stream_tag = ParseTagIndexFromStream(absl::StrCat(stream, ":u"));
|
||||
for (int i = streams->size() - 1; i >= 0; --i) {
|
||||
TagIndex tag = ParseTagIndexFromStream(streams->at(i));
|
||||
if (tag == stream_tag) {
|
||||
streams->erase(streams->begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the stream names for the container node.
|
||||
void GetContainerNodeStreams(const CalculatorGraphConfig::Node& node,
|
||||
CalculatorGraphConfig::Node* result) {
|
||||
CHECK(result != nullptr);
|
||||
*result->mutable_input_stream() = node.input_stream();
|
||||
*result->mutable_output_stream() = node.output_stream();
|
||||
*result->mutable_input_side_packet() = node.input_side_packet();
|
||||
*result->mutable_output_side_packet() = node.output_side_packet();
|
||||
EraseTag("ENABLE", result->mutable_input_stream());
|
||||
EraseTag("ENABLE", result->mutable_input_side_packet());
|
||||
EraseTag("SELECT", result->mutable_input_stream());
|
||||
EraseTag("SELECT", result->mutable_input_side_packet());
|
||||
}
|
||||
|
||||
// Validate all subgraph inputs and outputs.
|
||||
mediapipe::Status ValidateContract(
|
||||
const CalculatorGraphConfig::Node& subgraph_node,
|
||||
const Subgraph::SubgraphOptions& subgraph_options) {
|
||||
auto options =
|
||||
Subgraph::GetOptions<mediapipe::SwitchContainerOptions>(subgraph_options);
|
||||
std::map<TagIndex, std::string> input_tags, side_tags;
|
||||
ParseTags(subgraph_node.input_stream(), &input_tags);
|
||||
ParseTags(subgraph_node.input_side_packet(), &side_tags);
|
||||
if (options.has_select() && options.has_enable()) {
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"Only one of SwitchContainer options 'enable' and 'select' can be "
|
||||
"specified");
|
||||
}
|
||||
if (side_tags.count({"SELECT", 0}) + side_tags.count({"ENABLE", 0}) > 1 ||
|
||||
input_tags.count({"SELECT", 0}) + input_tags.count({"ENABLE", 0}) > 1) {
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"Only one of SwitchContainer inputs 'ENABLE' and 'SELECT' can be "
|
||||
"specified");
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::StatusOr<CalculatorGraphConfig> SwitchContainer::GetConfig(
|
||||
const Subgraph::SubgraphOptions& options) {
|
||||
CalculatorGraphConfig config;
|
||||
std::vector<CalculatorGraphConfig::Node*> subnodes;
|
||||
std::vector<CalculatorGraphConfig::Node> substreams;
|
||||
|
||||
// Parse all input and output tags from the container node.
|
||||
auto container_node = Subgraph::GetNode(options);
|
||||
MP_RETURN_IF_ERROR(ValidateContract(container_node, options));
|
||||
CalculatorGraphConfig::Node container_streams;
|
||||
GetContainerNodeStreams(container_node, &container_streams);
|
||||
std::map<TagIndex, std::string> input_tags, output_tags;
|
||||
std::map<TagIndex, std::string> side_input_tags, side_output_tags;
|
||||
ParseTags(container_streams.input_stream(), &input_tags);
|
||||
ParseTags(container_streams.output_stream(), &output_tags);
|
||||
ParseTags(container_streams.input_side_packet(), &side_input_tags);
|
||||
ParseTags(container_streams.output_side_packet(), &side_output_tags);
|
||||
|
||||
// Add a graph node for the demux, mux.
|
||||
auto demux = BuildDemuxNode(input_tags, &config);
|
||||
demux->add_input_stream("SELECT:gate_select");
|
||||
demux->add_input_stream("ENABLE:gate_enable");
|
||||
demux->add_input_side_packet("SELECT:gate_select");
|
||||
demux->add_input_side_packet("ENABLE:gate_enable");
|
||||
|
||||
auto mux = BuildMuxNode(output_tags, &config);
|
||||
mux->add_input_stream("SELECT:gate_select");
|
||||
mux->add_input_stream("ENABLE:gate_enable");
|
||||
mux->add_input_side_packet("SELECT:gate_select");
|
||||
mux->add_input_side_packet("ENABLE:gate_enable");
|
||||
|
||||
// Add input streams for graph and demux.
|
||||
config.add_input_stream("SELECT:gate_select");
|
||||
config.add_input_stream("ENABLE:gate_enable");
|
||||
config.add_input_side_packet("SELECT:gate_select");
|
||||
config.add_input_side_packet("ENABLE:gate_enable");
|
||||
for (const auto& p : input_tags) {
|
||||
std::string stream = CatStream(p.first, p.second);
|
||||
config.add_input_stream(stream);
|
||||
demux->add_input_stream(stream);
|
||||
}
|
||||
|
||||
// Add output streams for graph and mux.
|
||||
for (const auto& p : output_tags) {
|
||||
std::string stream = CatStream(p.first, p.second);
|
||||
config.add_output_stream(stream);
|
||||
mux->add_output_stream(stream);
|
||||
}
|
||||
for (const auto& p : side_input_tags) {
|
||||
std::string side = CatStream(p.first, p.second);
|
||||
config.add_input_side_packet(side);
|
||||
demux->add_input_side_packet(side);
|
||||
}
|
||||
for (const auto& p : side_output_tags) {
|
||||
std::string side = CatStream(p.first, p.second);
|
||||
config.add_output_side_packet(side);
|
||||
mux->add_output_side_packet(side);
|
||||
}
|
||||
|
||||
// Add a subnode for each contained_node.
|
||||
auto nodes = Subgraph::GetOptions<mediapipe::SwitchContainerOptions>(options)
|
||||
.contained_node();
|
||||
std::vector<CalculatorGraphConfig::Node> contained_nodes(nodes.begin(),
|
||||
nodes.end());
|
||||
for (int i = 0; i < contained_nodes.size(); ++i) {
|
||||
auto subnode = config.add_node();
|
||||
*subnode = contained_nodes[i];
|
||||
subnodes.push_back(subnode);
|
||||
substreams.push_back(container_streams);
|
||||
}
|
||||
|
||||
// Connect each contained graph node to demux and mux.
|
||||
for (int channel = 0; channel < subnodes.size(); ++channel) {
|
||||
CalculatorGraphConfig::Node& streams = substreams[channel];
|
||||
|
||||
// Connect each contained graph node input to a demux output.
|
||||
std::map<TagIndex, std::string> input_stream_tags;
|
||||
ParseTags(streams.input_stream(), &input_stream_tags);
|
||||
for (auto& it : input_stream_tags) {
|
||||
TagIndex tag_index = it.first;
|
||||
std::string tag = ChannelTag(tag_index.first, channel);
|
||||
std::string name = ChannelName(input_tags[tag_index], channel);
|
||||
std::string demux_stream = CatStream({tag, tag_index.second}, name);
|
||||
demux->add_output_stream(demux_stream);
|
||||
subnodes[channel]->add_input_stream(CatStream(tag_index, name));
|
||||
}
|
||||
|
||||
// Connect each contained graph node output to a mux input.
|
||||
std::map<TagIndex, std::string> output_stream_tags;
|
||||
ParseTags(streams.output_stream(), &output_stream_tags);
|
||||
for (auto& it : output_stream_tags) {
|
||||
TagIndex tag_index = it.first;
|
||||
std::string tag = ChannelTag(tag_index.first, channel);
|
||||
std::string name = ChannelName(output_tags[tag_index], channel);
|
||||
subnodes[channel]->add_output_stream(CatStream(tag_index, name));
|
||||
mux->add_input_stream(CatStream({tag, tag_index.second}, name));
|
||||
}
|
||||
|
||||
// Connect each contained graph node side-input to a demux side-output.
|
||||
std::map<TagIndex, std::string> input_side_tags;
|
||||
ParseTags(streams.input_side_packet(), &input_side_tags);
|
||||
for (auto& it : input_side_tags) {
|
||||
TagIndex tag_index = it.first;
|
||||
std::string tag = ChannelTag(tag_index.first, channel);
|
||||
std::string name = ChannelName(side_input_tags[tag_index], channel);
|
||||
std::string demux_stream = CatStream({tag, tag_index.second}, name);
|
||||
demux->add_output_side_packet(demux_stream);
|
||||
subnodes[channel]->add_input_side_packet(CatStream(tag_index, name));
|
||||
}
|
||||
|
||||
// Connect each contained graph node side-output to a mux side-input.
|
||||
std::map<TagIndex, std::string> output_side_tags;
|
||||
ParseTags(streams.output_side_packet(), &output_side_tags);
|
||||
for (auto& it : output_side_tags) {
|
||||
TagIndex tag_index = it.first;
|
||||
std::string tag = ChannelTag(tag_index.first, channel);
|
||||
std::string name = ChannelName(side_output_tags[tag_index], channel);
|
||||
subnodes[channel]->add_output_side_packet(CatStream(tag_index, name));
|
||||
mux->add_input_side_packet(CatStream({tag, tag_index.second}, name));
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,27 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option java_package = "com.google.mediapipe.proto";
|
||||
option java_outer_classname = "SwitchContainerProto";
|
||||
|
||||
// Options for a switch-container directing traffic to one of several
|
||||
// contained subgraph or calculator nodes.
|
||||
message SwitchContainerOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional SwitchContainerOptions ext = 345967970;
|
||||
}
|
||||
|
||||
reserved 1;
|
||||
|
||||
// The contained registered subgraphs or calculators.
|
||||
repeated CalculatorGraphConfig.Node contained_node = 2;
|
||||
|
||||
// Activates the specified channel to receive input packets.
|
||||
optional int32 select = 3;
|
||||
|
||||
// Activates channel 1 for enable = true, channel 0 otherwise.
|
||||
optional bool enable = 4;
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "mediapipe/framework/calculator.pb.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/deps/message_matchers.h"
|
||||
#include "mediapipe/framework/port/gmock.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
#include "mediapipe/framework/port/logging.h"
|
||||
#include "mediapipe/framework/port/parse_text_proto.h"
|
||||
#include "mediapipe/framework/port/proto_ns.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/framework/subgraph.h"
|
||||
#include "mediapipe/framework/tool/node_chain_subgraph.pb.h"
|
||||
#include "mediapipe/framework/tool/subgraph_expansion.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
|
||||
// A Calculator that outputs thrice the value of its input packet (an int).
|
||||
// It also accepts a side packet tagged "TIMEZONE", but doesn't use it.
|
||||
class TripleIntCalculator : public CalculatorBase {
|
||||
public:
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->Inputs().Index(0).Set<int>().Optional();
|
||||
cc->Outputs().Index(0).SetSameAs(&cc->Inputs().Index(0)).Optional();
|
||||
cc->InputSidePackets().Index(0).Set<int>().Optional();
|
||||
cc->OutputSidePackets()
|
||||
.Index(0)
|
||||
.SetSameAs(&cc->InputSidePackets().Index(0))
|
||||
.Optional();
|
||||
cc->InputSidePackets().Tag("TIMEZONE").Set<int>().Optional();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status Open(CalculatorContext* cc) final {
|
||||
cc->SetOffset(TimestampDiff(0));
|
||||
if (cc->OutputSidePackets().HasTag("")) {
|
||||
cc->OutputSidePackets().Index(0).Set(
|
||||
MakePacket<int>(cc->InputSidePackets().Index(0).Get<int>() * 3));
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
int value = cc->Inputs().Index(0).Value().Get<int>();
|
||||
cc->Outputs().Index(0).Add(new int(3 * value), cc->InputTimestamp());
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
};
|
||||
REGISTER_CALCULATOR(TripleIntCalculator);
|
||||
|
||||
// A testing example of a SwitchContainer containing two subnodes.
|
||||
// Note that the input and output tags supplied to the container node,
|
||||
// must match the input and output tags required by the subnodes.
|
||||
CalculatorGraphConfig SubnodeContainerExample() {
|
||||
return mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: "foo"
|
||||
input_stream: "enable"
|
||||
input_side_packet: "timezone"
|
||||
node {
|
||||
calculator: "SwitchContainer"
|
||||
input_stream: "ENABLE:enable"
|
||||
input_stream: "foo"
|
||||
output_stream: "bar"
|
||||
options {
|
||||
[mediapipe.SwitchContainerOptions.ext] {
|
||||
contained_node: { calculator: "TripleIntCalculator" }
|
||||
contained_node: { calculator: "PassThroughCalculator" }
|
||||
}
|
||||
}
|
||||
}
|
||||
node {
|
||||
calculator: "PassThroughCalculator"
|
||||
input_stream: "foo"
|
||||
input_stream: "bar"
|
||||
output_stream: "output_foo"
|
||||
output_stream: "output_bar"
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
// A testing example of a SwitchContainer containing two subnodes.
|
||||
// Note that the side-input and side-output tags supplied to the container node,
|
||||
// must match the side-input and side-output tags required by the subnodes.
|
||||
CalculatorGraphConfig SideSubnodeContainerExample() {
|
||||
return mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "enable"
|
||||
output_side_packet: "output_bar"
|
||||
node {
|
||||
calculator: "SwitchContainer"
|
||||
input_side_packet: "ENABLE:enable"
|
||||
input_side_packet: "foo"
|
||||
output_side_packet: "bar"
|
||||
options {
|
||||
[mediapipe.SwitchContainerOptions.ext] {
|
||||
contained_node: { calculator: "TripleIntCalculator" }
|
||||
contained_node: { calculator: "PassThroughCalculator" }
|
||||
}
|
||||
}
|
||||
}
|
||||
node {
|
||||
calculator: "PassThroughCalculator"
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "bar"
|
||||
output_side_packet: "output_foo"
|
||||
output_side_packet: "output_bar"
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
// Runs the test container graph with a few input packets.
|
||||
void RunTestContainer(CalculatorGraphConfig supergraph) {
|
||||
CalculatorGraph graph;
|
||||
std::vector<Packet> out_foo, out_bar;
|
||||
tool::AddVectorSink("output_foo", &supergraph, &out_foo);
|
||||
tool::AddVectorSink("output_bar", &supergraph, &out_bar);
|
||||
MP_ASSERT_OK(graph.Initialize(supergraph, {}));
|
||||
MP_ASSERT_OK(graph.StartRun({{"timezone", MakePacket<int>(3)}}));
|
||||
|
||||
// Send enable == true signal at 5000 us.
|
||||
const int64 enable_ts = 5000;
|
||||
MP_EXPECT_OK(graph.AddPacketToInputStream(
|
||||
"enable", MakePacket<bool>(true).At(Timestamp(enable_ts))));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
const int packet_count = 10;
|
||||
// Send int value packets at {10K, 20K, 30K, ..., 100K}.
|
||||
for (uint64 t = 1; t <= packet_count; ++t) {
|
||||
MP_EXPECT_OK(graph.AddPacketToInputStream(
|
||||
"foo", MakePacket<int>(t).At(Timestamp(t * 10000))));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
// The inputs are sent to the input stream "foo", they should pass through.
|
||||
EXPECT_EQ(out_foo.size(), t);
|
||||
// Since "enable == true" for ts 10K...100K us, the second contained graph
|
||||
// i.e. the one containing the PassThroughCalculator should output the
|
||||
// input values without changing them.
|
||||
EXPECT_EQ(out_bar.size(), t);
|
||||
EXPECT_EQ(out_bar.back().Get<int>(), t);
|
||||
}
|
||||
|
||||
// Send enable == false signal at 105K us.
|
||||
MP_EXPECT_OK(graph.AddPacketToInputStream(
|
||||
"enable", MakePacket<bool>(false).At(Timestamp(105000))));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
// Send int value packets at {110K, 120K, ..., 200K}.
|
||||
for (uint64 t = 11; t <= packet_count * 2; ++t) {
|
||||
MP_EXPECT_OK(graph.AddPacketToInputStream(
|
||||
"foo", MakePacket<int>(t).At(Timestamp(t * 10000))));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
// The inputs are sent to the input stream "foo", they should pass through.
|
||||
EXPECT_EQ(out_foo.size(), t);
|
||||
// Since "enable == false" for ts 110K...200K us, the first contained graph
|
||||
// i.e. the one containing the TripleIntCalculator should output the values
|
||||
// after tripling them.
|
||||
EXPECT_EQ(out_bar.size(), t);
|
||||
EXPECT_EQ(out_bar.back().Get<int>(), t * 3);
|
||||
}
|
||||
|
||||
MP_ASSERT_OK(graph.CloseAllInputStreams());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
EXPECT_EQ(out_foo.size(), packet_count * 2);
|
||||
EXPECT_EQ(out_bar.size(), packet_count * 2);
|
||||
}
|
||||
|
||||
// Runs the test side-packet container graph with input side-packets.
|
||||
void RunTestSideContainer(CalculatorGraphConfig supergraph) {
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(supergraph, {}));
|
||||
MP_ASSERT_OK(graph.StartRun({
|
||||
{"enable", MakePacket<bool>(false)},
|
||||
{"foo", MakePacket<int>(4)},
|
||||
}));
|
||||
MP_ASSERT_OK(graph.CloseAllInputStreams());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
Packet side_output = graph.GetOutputSidePacket("output_bar").ValueOrDie();
|
||||
EXPECT_EQ(side_output.Get<int>(), 12);
|
||||
|
||||
MP_ASSERT_OK(graph.StartRun({
|
||||
{"enable", MakePacket<bool>(true)},
|
||||
{"foo", MakePacket<int>(4)},
|
||||
}));
|
||||
MP_ASSERT_OK(graph.CloseAllInputStreams());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
side_output = graph.GetOutputSidePacket("output_bar").ValueOrDie();
|
||||
EXPECT_EQ(side_output.Get<int>(), 4);
|
||||
}
|
||||
|
||||
// Rearrange the Node messages within a CalculatorGraphConfig message.
|
||||
CalculatorGraphConfig OrderNodes(const CalculatorGraphConfig& config,
|
||||
std::vector<int> order) {
|
||||
auto result = config;
|
||||
result.clear_node();
|
||||
for (int i = 0; i < order.size(); ++i) {
|
||||
*result.add_node() = config.node(order[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Shows the SwitchContainer container applied to a pair of simple subnodes.
|
||||
TEST(SwitchContainerTest, ApplyToSubnodes) {
|
||||
EXPECT_TRUE(SubgraphRegistry::IsRegistered("SwitchContainer"));
|
||||
CalculatorGraphConfig supergraph = SubnodeContainerExample();
|
||||
CalculatorGraphConfig expected_graph =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
name: "switchcontainer__SwitchDemuxCalculator"
|
||||
calculator: "SwitchDemuxCalculator"
|
||||
input_stream: "ENABLE:enable"
|
||||
input_stream: "foo"
|
||||
output_stream: "C0__:switchcontainer__c0__foo"
|
||||
output_stream: "C1__:switchcontainer__c1__foo"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__TripleIntCalculator"
|
||||
calculator: "TripleIntCalculator"
|
||||
input_stream: "switchcontainer__c0__foo"
|
||||
output_stream: "switchcontainer__c0__bar"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__PassThroughCalculator"
|
||||
calculator: "PassThroughCalculator"
|
||||
input_stream: "switchcontainer__c1__foo"
|
||||
output_stream: "switchcontainer__c1__bar"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__SwitchMuxCalculator"
|
||||
calculator: "SwitchMuxCalculator"
|
||||
input_stream: "ENABLE:enable"
|
||||
input_stream: "C0__:switchcontainer__c0__bar"
|
||||
input_stream: "C1__:switchcontainer__c1__bar"
|
||||
output_stream: "bar"
|
||||
}
|
||||
node {
|
||||
calculator: "PassThroughCalculator"
|
||||
input_stream: "foo"
|
||||
input_stream: "bar"
|
||||
output_stream: "output_foo"
|
||||
output_stream: "output_bar"
|
||||
}
|
||||
input_stream: "foo"
|
||||
input_stream: "enable"
|
||||
input_side_packet: "timezone"
|
||||
)");
|
||||
expected_graph = OrderNodes(expected_graph, {4, 0, 3, 1, 2});
|
||||
MP_EXPECT_OK(tool::ExpandSubgraphs(&supergraph));
|
||||
EXPECT_THAT(supergraph, mediapipe::EqualsProto(expected_graph));
|
||||
}
|
||||
|
||||
// Shows the SwitchContainer container runs with a pair of simple subnodes.
|
||||
TEST(SwitchContainerTest, RunsWithSubnodes) {
|
||||
EXPECT_TRUE(SubgraphRegistry::IsRegistered("SwitchContainer"));
|
||||
CalculatorGraphConfig supergraph = SubnodeContainerExample();
|
||||
MP_EXPECT_OK(tool::ExpandSubgraphs(&supergraph));
|
||||
RunTestContainer(supergraph);
|
||||
}
|
||||
|
||||
// Shows the SwitchContainer container applied to a pair of simple subnodes.
|
||||
TEST(SwitchContainerTest, ApplyToSideSubnodes) {
|
||||
EXPECT_TRUE(SubgraphRegistry::IsRegistered("SwitchContainer"));
|
||||
CalculatorGraphConfig supergraph = SideSubnodeContainerExample();
|
||||
CalculatorGraphConfig expected_graph =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "enable"
|
||||
output_side_packet: "output_bar"
|
||||
node {
|
||||
name: "switchcontainer__SwitchDemuxCalculator"
|
||||
calculator: "SwitchDemuxCalculator"
|
||||
input_side_packet: "ENABLE:enable"
|
||||
input_side_packet: "foo"
|
||||
output_side_packet: "C0__:switchcontainer__c0__foo"
|
||||
output_side_packet: "C1__:switchcontainer__c1__foo"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__TripleIntCalculator"
|
||||
calculator: "TripleIntCalculator"
|
||||
input_side_packet: "switchcontainer__c0__foo"
|
||||
output_side_packet: "switchcontainer__c0__bar"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__PassThroughCalculator"
|
||||
calculator: "PassThroughCalculator"
|
||||
input_side_packet: "switchcontainer__c1__foo"
|
||||
output_side_packet: "switchcontainer__c1__bar"
|
||||
}
|
||||
node {
|
||||
name: "switchcontainer__SwitchMuxCalculator"
|
||||
calculator: "SwitchMuxCalculator"
|
||||
input_side_packet: "ENABLE:enable"
|
||||
input_side_packet: "C0__:switchcontainer__c0__bar"
|
||||
input_side_packet: "C1__:switchcontainer__c1__bar"
|
||||
output_side_packet: "bar"
|
||||
}
|
||||
node {
|
||||
calculator: "PassThroughCalculator"
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "bar"
|
||||
output_side_packet: "output_foo"
|
||||
output_side_packet: "output_bar"
|
||||
}
|
||||
)");
|
||||
expected_graph = OrderNodes(expected_graph, {4, 0, 3, 1, 2});
|
||||
MP_EXPECT_OK(tool::ExpandSubgraphs(&supergraph));
|
||||
EXPECT_THAT(supergraph, mediapipe::EqualsProto(expected_graph));
|
||||
}
|
||||
|
||||
// Shows the SwitchContainer container runs with a pair of simple subnodes.
|
||||
TEST(SwitchContainerTest, RunWithSideSubnodes) {
|
||||
EXPECT_TRUE(SubgraphRegistry::IsRegistered("SwitchContainer"));
|
||||
CalculatorGraphConfig supergraph = SideSubnodeContainerExample();
|
||||
MP_EXPECT_OK(tool::ExpandSubgraphs(&supergraph));
|
||||
RunTestSideContainer(supergraph);
|
||||
}
|
||||
|
||||
// Shows validation of SwitchContainer container side inputs.
|
||||
TEST(SwitchContainerTest, ValidateSideInputs) {
|
||||
EXPECT_TRUE(SubgraphRegistry::IsRegistered("SwitchContainer"));
|
||||
CalculatorGraphConfig supergraph =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "enable"
|
||||
output_side_packet: "output_bar"
|
||||
node {
|
||||
calculator: "SwitchContainer"
|
||||
input_side_packet: "ENABLE:enable"
|
||||
input_side_packet: "SELECT:enable"
|
||||
input_side_packet: "foo"
|
||||
output_side_packet: "bar"
|
||||
options {
|
||||
[mediapipe.SwitchContainerOptions.ext] {
|
||||
contained_node: { calculator: "TripleIntCalculator" }
|
||||
contained_node: { calculator: "PassThroughCalculator" }
|
||||
}
|
||||
}
|
||||
}
|
||||
node {
|
||||
calculator: "PassThroughCalculator"
|
||||
input_side_packet: "foo"
|
||||
input_side_packet: "bar"
|
||||
output_side_packet: "output_foo"
|
||||
output_side_packet: "output_bar"
|
||||
}
|
||||
)");
|
||||
auto status = tool::ExpandSubgraphs(&supergraph);
|
||||
EXPECT_EQ(std::pair(status.code(), std::string(status.message())),
|
||||
std::pair(mediapipe::StatusCode::kInvalidArgument,
|
||||
std::string("Only one of SwitchContainer inputs "
|
||||
"'ENABLE' and 'SELECT' can be specified")));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/collection_item_id.h"
|
||||
#include "mediapipe/framework/port/integral_types.h"
|
||||
#include "mediapipe/framework/port/logging.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/port/status_macros.h"
|
||||
#include "mediapipe/framework/tool/container_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
// A calculator to redirect a set of input streams to one of several output
|
||||
// channels, each consisting of corresponding output streams. Each channel
|
||||
// is distinguished by a tag-prefix such as "C1__". For example:
|
||||
//
|
||||
// node {
|
||||
// calculator: "SwitchDemuxCalculator"
|
||||
// input_stream: "ENABLE:enable"
|
||||
// input_stream: "FUNC_INPUT:foo"
|
||||
// input_stream: "FUNC_INPUT:bar"
|
||||
// output_stream: "C0__FUNC_INPUT:foo_0"
|
||||
// output_stream: "C0__FUNC_INPUT:bar_0"
|
||||
// output_stream: "C1__FUNC_INPUT:foo_1"
|
||||
// output_stream: "C1__FUNC_INPUT:bar_1"
|
||||
// }
|
||||
//
|
||||
// Input stream "ENABLE" specifies routing of packets to either channel 0
|
||||
// or channel 1, given "ENABLE:false" or "ENABLE:true" respectively.
|
||||
// Input-side-packet "ENABLE" and input-stream "SELECT" can also be used
|
||||
// similarly to specify the active channel.
|
||||
//
|
||||
// SwitchDemuxCalculator is used by SwitchContainer to enable one of several
|
||||
// contained subgraph or calculator nodes.
|
||||
//
|
||||
class SwitchDemuxCalculator : public CalculatorBase {
|
||||
static constexpr char kSelectTag[] = "SELECT";
|
||||
static constexpr char kEnableTag[] = "ENABLE";
|
||||
|
||||
public:
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
|
||||
mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
int channel_index_;
|
||||
std::set<std::string> channel_tags_;
|
||||
};
|
||||
REGISTER_CALCULATOR(SwitchDemuxCalculator);
|
||||
|
||||
mediapipe::Status SwitchDemuxCalculator::GetContract(CalculatorContract* cc) {
|
||||
// Allow any one of kSelectTag, kEnableTag.
|
||||
if (cc->Inputs().HasTag(kSelectTag)) {
|
||||
cc->Inputs().Tag(kSelectTag).Set<int>();
|
||||
} else if (cc->Inputs().HasTag(kEnableTag)) {
|
||||
cc->Inputs().Tag(kEnableTag).Set<bool>();
|
||||
}
|
||||
// Allow any one of kSelectTag, kEnableTag.
|
||||
if (cc->InputSidePackets().HasTag(kSelectTag)) {
|
||||
cc->InputSidePackets().Tag(kSelectTag).Set<int>();
|
||||
} else if (cc->InputSidePackets().HasTag(kEnableTag)) {
|
||||
cc->InputSidePackets().Tag(kEnableTag).Set<bool>();
|
||||
}
|
||||
|
||||
// Set the types for all output channels to corresponding input types.
|
||||
std::set<std::string> channel_tags = ChannelTags(cc->Outputs().TagMap());
|
||||
int channel_count = ChannelCount(cc->Outputs().TagMap());
|
||||
for (const std::string& tag : channel_tags) {
|
||||
for (int index = 0; index < cc->Inputs().NumEntries(tag); ++index) {
|
||||
auto input_id = cc->Inputs().GetId(tag, index);
|
||||
if (input_id.IsValid()) {
|
||||
cc->Inputs().Get(tag, index).SetAny();
|
||||
for (int channel = 0; channel < channel_count; ++channel) {
|
||||
auto output_id =
|
||||
cc->Outputs().GetId(tool::ChannelTag(tag, channel), index);
|
||||
if (output_id.IsValid()) {
|
||||
cc->Outputs().Get(output_id).SetSameAs(&cc->Inputs().Get(input_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
channel_tags = ChannelTags(cc->OutputSidePackets().TagMap());
|
||||
channel_count = ChannelCount(cc->OutputSidePackets().TagMap());
|
||||
for (const std::string& tag : channel_tags) {
|
||||
int num_entries = cc->InputSidePackets().NumEntries(tag);
|
||||
for (int index = 0; index < num_entries; ++index) {
|
||||
auto input_id = cc->InputSidePackets().GetId(tag, index);
|
||||
if (input_id.IsValid()) {
|
||||
cc->InputSidePackets().Get(tag, index).SetAny();
|
||||
for (int channel = 0; channel < channel_count; ++channel) {
|
||||
auto output_id = cc->OutputSidePackets().GetId(
|
||||
tool::ChannelTag(tag, channel), index);
|
||||
if (output_id.IsValid()) {
|
||||
cc->OutputSidePackets().Get(output_id).SetSameAs(
|
||||
&cc->InputSidePackets().Get(input_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cc->SetInputStreamHandler("ImmediateInputStreamHandler");
|
||||
cc->SetProcessTimestampBounds(true);
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status SwitchDemuxCalculator::Open(CalculatorContext* cc) {
|
||||
channel_index_ = tool::GetChannelIndex(*cc, channel_index_);
|
||||
channel_tags_ = ChannelTags(cc->Outputs().TagMap());
|
||||
|
||||
// Relay side packets to all channels.
|
||||
// Note: This is necessary because Calculator::Open only proceeds when every
|
||||
// anticipated side-packet arrives.
|
||||
int channel_count = tool::ChannelCount(cc->OutputSidePackets().TagMap());
|
||||
for (const std::string& tag : ChannelTags(cc->OutputSidePackets().TagMap())) {
|
||||
int num_entries = cc->InputSidePackets().NumEntries(tag);
|
||||
for (int index = 0; index < num_entries; ++index) {
|
||||
Packet input = cc->InputSidePackets().Get(tag, index);
|
||||
for (int channel = 0; channel < channel_count; ++channel) {
|
||||
std::string output_tag = tool::ChannelTag(tag, channel);
|
||||
auto output_id = cc->OutputSidePackets().GetId(output_tag, index);
|
||||
if (output_id.IsValid()) {
|
||||
cc->OutputSidePackets().Get(output_tag, index).Set(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status SwitchDemuxCalculator::Process(CalculatorContext* cc) {
|
||||
// Update the input channel index if specified.
|
||||
channel_index_ = tool::GetChannelIndex(*cc, channel_index_);
|
||||
|
||||
// Relay packets and timestamps only to channel_index_.
|
||||
for (const std::string& tag : channel_tags_) {
|
||||
for (int index = 0; index < cc->Inputs().NumEntries(tag); ++index) {
|
||||
auto& input = cc->Inputs().Get(tag, index);
|
||||
std::string output_tag = tool::ChannelTag(tag, channel_index_);
|
||||
auto output_id = cc->Outputs().GetId(output_tag, index);
|
||||
if (output_id.IsValid()) {
|
||||
auto& output = cc->Outputs().Get(output_tag, index);
|
||||
tool::Relay(input, &output);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/collection_item_id.h"
|
||||
#include "mediapipe/framework/input_stream_shard.h"
|
||||
#include "mediapipe/framework/output_stream_shard.h"
|
||||
#include "mediapipe/framework/port/integral_types.h"
|
||||
#include "mediapipe/framework/port/logging.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/port/status_macros.h"
|
||||
#include "mediapipe/framework/tool/container_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
// A calculator to join several sets of input streams into one
|
||||
// output channel, consisting of corresponding output streams.
|
||||
// Each channel is distinguished by a tag-prefix such as "C1__".
|
||||
// For example:
|
||||
//
|
||||
// node {
|
||||
// calculator: "SwitchMuxCalculator"
|
||||
// input_stream: "ENABLE:enable"
|
||||
// input_stream: "C0__FUNC_INPUT:foo_0"
|
||||
// input_stream: "C0__FUNC_INPUT:bar_0"
|
||||
// input_stream: "C1__FUNC_INPUT:foo_1"
|
||||
// input_stream: "C1__FUNC_INPUT:bar_1"
|
||||
// output_stream: "FUNC_INPUT:foo"
|
||||
// output_stream: "FUNC_INPUT:bar"
|
||||
// }
|
||||
//
|
||||
// Input stream "ENABLE" specifies routing of packets from either channel 0
|
||||
// or channel 1, given "ENABLE:false" or "ENABLE:true" respectively.
|
||||
// Input-side-packet "ENABLE" and input-stream "SELECT" can also be used
|
||||
// similarly to specify the active channel.
|
||||
//
|
||||
// SwitchMuxCalculator is used by SwitchContainer to enable one of several
|
||||
// contained subgraph or calculator nodes.
|
||||
//
|
||||
class SwitchMuxCalculator : public CalculatorBase {
|
||||
static constexpr char kSelectTag[] = "SELECT";
|
||||
static constexpr char kEnableTag[] = "ENABLE";
|
||||
|
||||
public:
|
||||
static mediapipe::Status GetContract(CalculatorContract* cc);
|
||||
|
||||
mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
int channel_index_;
|
||||
std::set<std::string> channel_tags_;
|
||||
};
|
||||
REGISTER_CALCULATOR(SwitchMuxCalculator);
|
||||
|
||||
mediapipe::Status SwitchMuxCalculator::GetContract(CalculatorContract* cc) {
|
||||
// Allow any one of kSelectTag, kEnableTag.
|
||||
if (cc->Inputs().HasTag(kSelectTag)) {
|
||||
cc->Inputs().Tag(kSelectTag).Set<int>();
|
||||
} else if (cc->Inputs().HasTag(kEnableTag)) {
|
||||
cc->Inputs().Tag(kEnableTag).Set<bool>();
|
||||
}
|
||||
// Allow any one of kSelectTag, kEnableTag.
|
||||
if (cc->InputSidePackets().HasTag(kSelectTag)) {
|
||||
cc->InputSidePackets().Tag(kSelectTag).Set<int>();
|
||||
} else if (cc->InputSidePackets().HasTag(kEnableTag)) {
|
||||
cc->InputSidePackets().Tag(kEnableTag).Set<bool>();
|
||||
}
|
||||
|
||||
// Set the types for all input channels to corresponding output types.
|
||||
std::set<std::string> channel_tags = ChannelTags(cc->Inputs().TagMap());
|
||||
int channel_count = ChannelCount(cc->Inputs().TagMap());
|
||||
for (const std::string& tag : channel_tags) {
|
||||
for (int index = 0; index < cc->Outputs().NumEntries(tag); ++index) {
|
||||
cc->Outputs().Get(tag, index).SetAny();
|
||||
auto output_id = cc->Outputs().GetId(tag, index);
|
||||
if (output_id.IsValid()) {
|
||||
for (int channel = 0; channel < channel_count; ++channel) {
|
||||
auto input_id =
|
||||
cc->Inputs().GetId(tool::ChannelTag(tag, channel), index);
|
||||
if (input_id.IsValid()) {
|
||||
cc->Inputs().Get(input_id).SetSameAs(&cc->Outputs().Get(output_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
channel_tags = ChannelTags(cc->InputSidePackets().TagMap());
|
||||
channel_count = ChannelCount(cc->InputSidePackets().TagMap());
|
||||
for (const std::string& tag : channel_tags) {
|
||||
int num_entries = cc->OutputSidePackets().NumEntries(tag);
|
||||
for (int index = 0; index < num_entries; ++index) {
|
||||
cc->OutputSidePackets().Get(tag, index).SetAny();
|
||||
auto output_id = cc->OutputSidePackets().GetId(tag, index);
|
||||
if (output_id.IsValid()) {
|
||||
for (int channel = 0; channel < channel_count; ++channel) {
|
||||
auto input_id = cc->InputSidePackets().GetId(
|
||||
tool::ChannelTag(tag, channel), index);
|
||||
if (input_id.IsValid()) {
|
||||
cc->InputSidePackets().Get(input_id).SetSameAs(
|
||||
&cc->OutputSidePackets().Get(output_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cc->SetInputStreamHandler("ImmediateInputStreamHandler");
|
||||
cc->SetProcessTimestampBounds(true);
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status SwitchMuxCalculator::Open(CalculatorContext* cc) {
|
||||
channel_index_ = tool::GetChannelIndex(*cc, channel_index_);
|
||||
channel_tags_ = ChannelTags(cc->Inputs().TagMap());
|
||||
|
||||
// Relay side packets only from channel_index_.
|
||||
for (const std::string& tag : ChannelTags(cc->InputSidePackets().TagMap())) {
|
||||
int num_outputs = cc->OutputSidePackets().NumEntries(tag);
|
||||
for (int index = 0; index < num_outputs; ++index) {
|
||||
std::string input_tag = tool::ChannelTag(tag, channel_index_);
|
||||
Packet input = cc->InputSidePackets().Get(input_tag, index);
|
||||
cc->OutputSidePackets().Get(tag, index).Set(input);
|
||||
}
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
mediapipe::Status SwitchMuxCalculator::Process(CalculatorContext* cc) {
|
||||
// Update the input channel index if specified.
|
||||
channel_index_ = tool::GetChannelIndex(*cc, channel_index_);
|
||||
|
||||
// Relay packets and timestamps only from channel_index_.
|
||||
for (const std::string& tag : channel_tags_) {
|
||||
for (int index = 0; index < cc->Outputs().NumEntries(tag); ++index) {
|
||||
auto& output = cc->Outputs().Get(tag, index);
|
||||
std::string input_tag = tool::ChannelTag(tag, channel_index_);
|
||||
auto& input = cc->Inputs().Get(input_tag, index);
|
||||
tool::Relay(input, &output);
|
||||
}
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace mediapipe
|
||||
@@ -37,7 +37,7 @@ void TagMap::InitializeNames(
|
||||
}
|
||||
}
|
||||
|
||||
::mediapipe::Status TagMap::Initialize(
|
||||
mediapipe::Status TagMap::Initialize(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& tag_index_names) {
|
||||
std::map<std::string, std::vector<std::string>> tag_to_names;
|
||||
for (const auto& tag_index_name : tag_index_names) {
|
||||
@@ -63,7 +63,7 @@ void TagMap::InitializeNames(
|
||||
names.resize(index + 1);
|
||||
}
|
||||
if (!names[index].empty()) {
|
||||
return ::mediapipe::FailedPreconditionErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::FailedPreconditionErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "tag \"" << tag << "\" index " << index
|
||||
<< " already had a name \"" << names[index]
|
||||
<< "\" but is being reassigned a name \"" << name << "\"";
|
||||
@@ -81,7 +81,7 @@ void TagMap::InitializeNames(
|
||||
// loop above), this means that all indexes were used exactly once.
|
||||
const std::vector<std::string>& names = tag_to_names[item.first];
|
||||
if (tag_data.count != names.size()) {
|
||||
auto builder = ::mediapipe::FailedPreconditionErrorBuilder(MEDIAPIPE_LOC)
|
||||
auto builder = mediapipe::FailedPreconditionErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Not all indexes were assigned names. Tag \""
|
||||
<< item.first << "\" has the following:\n";
|
||||
// Note, names.size() will always be larger than tag_data.count.
|
||||
@@ -100,10 +100,10 @@ void TagMap::InitializeNames(
|
||||
num_entries_ = current_index;
|
||||
|
||||
InitializeNames(tag_to_names);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status TagMap::Initialize(const TagAndNameInfo& info) {
|
||||
mediapipe::Status TagMap::Initialize(const TagAndNameInfo& info) {
|
||||
if (info.tags.empty()) {
|
||||
if (!info.names.empty()) {
|
||||
mapping_.emplace(
|
||||
@@ -115,7 +115,7 @@ void TagMap::InitializeNames(
|
||||
} else {
|
||||
std::map<std::string, std::vector<std::string>> tag_to_names;
|
||||
if (info.tags.size() != info.names.size()) {
|
||||
return ::mediapipe::FailedPreconditionError(
|
||||
return mediapipe::FailedPreconditionError(
|
||||
"Expected info.tags.size() == info.names.size()");
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ void TagMap::InitializeNames(
|
||||
// Now create the names_ array in the correctly sorted order.
|
||||
InitializeNames(tag_to_names);
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
proto_ns::RepeatedPtrField<ProtoString> TagMap::CanonicalEntries() const {
|
||||
|
||||
@@ -53,7 +53,7 @@ class TagMap {
|
||||
// TAG:<index>:name. This is the most common usage:
|
||||
// ASSIGN_OR_RETURN(std::shared_ptr<TagMap> tag_map,
|
||||
// tool::TagMap::Create(node.input_streams()));
|
||||
static ::mediapipe::StatusOr<std::shared_ptr<TagMap>> Create(
|
||||
static mediapipe::StatusOr<std::shared_ptr<TagMap>> Create(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& tag_index_names) {
|
||||
std::shared_ptr<TagMap> output(new TagMap());
|
||||
MP_RETURN_IF_ERROR(output->Initialize(tag_index_names));
|
||||
@@ -64,7 +64,7 @@ class TagMap {
|
||||
// TODO: Migrate callers and delete this method.
|
||||
ABSL_DEPRECATED(
|
||||
"Use mediapipe::tool::TagMap::Create(tag_index_names) instead.")
|
||||
static ::mediapipe::StatusOr<std::shared_ptr<TagMap>> Create(
|
||||
static mediapipe::StatusOr<std::shared_ptr<TagMap>> Create(
|
||||
const TagAndNameInfo& info) {
|
||||
std::shared_ptr<TagMap> output(new TagMap());
|
||||
MP_RETURN_IF_ERROR(output->Initialize(info));
|
||||
@@ -108,12 +108,12 @@ class TagMap {
|
||||
|
||||
// Initialize the TagMap. Due to only having a factory function for
|
||||
// creation, there is no way for a user to have an uninitialized TagMap.
|
||||
::mediapipe::Status Initialize(
|
||||
mediapipe::Status Initialize(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& tag_index_names);
|
||||
|
||||
// Initialize from a TagAndNameInfo.
|
||||
ABSL_DEPRECATED("Use Initialize(tag_index_names) instead.")
|
||||
::mediapipe::Status Initialize(const TagAndNameInfo& info);
|
||||
mediapipe::Status Initialize(const TagAndNameInfo& info);
|
||||
|
||||
// Initialize names_ using a map from tag to the names for that tag.
|
||||
void InitializeNames(
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
// Create using a vector of TAG:<index>:name.
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(
|
||||
const std::vector<std::string>& tag_index_names) {
|
||||
proto_ns::RepeatedPtrField<ProtoString> fields;
|
||||
for (const auto& tag_index_name : tag_index_names) {
|
||||
@@ -41,7 +41,7 @@ namespace tool {
|
||||
}
|
||||
|
||||
// Create using an integer number of entries (for tag "").
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(int num_entries) {
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(int num_entries) {
|
||||
RET_CHECK_LE(0, num_entries);
|
||||
proto_ns::RepeatedPtrField<ProtoString> fields;
|
||||
for (int i = 0; i < num_entries; ++i) {
|
||||
@@ -51,7 +51,7 @@ namespace tool {
|
||||
}
|
||||
|
||||
// Create using a vector of just tag names.
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMapFromTags(
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMapFromTags(
|
||||
const std::vector<std::string>& tags) {
|
||||
proto_ns::RepeatedPtrField<ProtoString> fields;
|
||||
for (int i = 0; i < tags.size(); ++i) {
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
// Create a TagMap using a vector of TAG:<index>:name.
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(
|
||||
const std::vector<std::string>& tag_index_names);
|
||||
|
||||
// Create a TagMap using an integer number of entries (for tag "").
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(int num_entries);
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMap(int num_entries);
|
||||
|
||||
// Create a TagMap using a vector of just tag names.
|
||||
::mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMapFromTags(
|
||||
mediapipe::StatusOr<std::shared_ptr<TagMap>> CreateTagMapFromTags(
|
||||
const std::vector<std::string>& tags);
|
||||
|
||||
} // namespace tool
|
||||
|
||||
@@ -101,7 +101,7 @@ void TestSuccessTagMap(const std::vector<std::string>& tag_index_names,
|
||||
EXPECT_EQ(tags.size(), tag_map->Mapping().size())
|
||||
<< "Parameters: in " << tag_map->DebugString();
|
||||
for (int i = 0; i < tags.size(); ++i) {
|
||||
EXPECT_TRUE(::mediapipe::ContainsKey(tag_map->Mapping(), tags[i]))
|
||||
EXPECT_TRUE(mediapipe::ContainsKey(tag_map->Mapping(), tags[i]))
|
||||
<< "Parameters: Trying to find \"" << tags[i] << "\" in\n"
|
||||
<< tag_map->DebugString();
|
||||
}
|
||||
@@ -321,10 +321,10 @@ TEST(TagMapTest, SameAs) {
|
||||
// A helper function to test that a TagMap's debug std::string and short
|
||||
// debug std::string each satisfy a matcher.
|
||||
template <typename Matcher>
|
||||
void TestDebugString(const ::mediapipe::StatusOr<std::shared_ptr<tool::TagMap>>&
|
||||
statusor_tag_map,
|
||||
const std::vector<std::string>& canonical_entries,
|
||||
Matcher short_string_matcher) {
|
||||
void TestDebugString(
|
||||
const mediapipe::StatusOr<std::shared_ptr<tool::TagMap>>& statusor_tag_map,
|
||||
const std::vector<std::string>& canonical_entries,
|
||||
Matcher short_string_matcher) {
|
||||
MP_ASSERT_OK(statusor_tag_map);
|
||||
tool::TagMap& tag_map = *statusor_tag_map.ValueOrDie();
|
||||
std::string debug_string = tag_map.DebugString();
|
||||
|
||||
@@ -98,7 +98,7 @@ mediapipe::Status ProtoPathSplit(const std::string& path, ProtoPath* result) {
|
||||
bool ok = absl::SimpleAtoi(id_pair.first, &tag) &&
|
||||
absl::SimpleAtoi(id_pair.second, &index);
|
||||
if (!ok) {
|
||||
status.Update(::mediapipe::InvalidArgumentError(path));
|
||||
status.Update(mediapipe::InvalidArgumentError(path));
|
||||
}
|
||||
result->push_back(std::make_pair(tag, index));
|
||||
}
|
||||
@@ -146,7 +146,7 @@ int FieldCount(const FieldValue& base, ProtoPath field_path,
|
||||
// The default implementation for the mediapipe template rule interpreter.
|
||||
class TemplateExpanderImpl {
|
||||
public:
|
||||
explicit TemplateExpanderImpl(std::vector<::mediapipe::Status>* errors)
|
||||
explicit TemplateExpanderImpl(std::vector<mediapipe::Status>* errors)
|
||||
: errors_(errors) {}
|
||||
|
||||
// Applies the rules specified in a CalculatorGraphTemplate to a
|
||||
@@ -221,12 +221,12 @@ class TemplateExpanderImpl {
|
||||
std::vector<FieldValue>* base) {
|
||||
if (!rule.has_path()) {
|
||||
base->push_back(output);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
if (rule.has_field_value()) {
|
||||
// For a non-repeated field, the field value is stored only in the rule.
|
||||
base->push_back(rule.field_value());
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
ProtoPath field_path;
|
||||
mediapipe::Status status =
|
||||
@@ -242,7 +242,7 @@ class TemplateExpanderImpl {
|
||||
const std::vector<FieldValue>& field_values, FieldValue* output) {
|
||||
if (!rule.has_path()) {
|
||||
*output = field_values[0];
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
ProtoPath field_path;
|
||||
RET_CHECK_OK(
|
||||
@@ -252,7 +252,7 @@ class TemplateExpanderImpl {
|
||||
// For a non-repeated field, only one value can be specified.
|
||||
if (!field_values.empty() &&
|
||||
FieldCount(*output, field_path, GetFieldType(rule)) > 0) {
|
||||
return ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
return mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Multiple values specified for non-repeated field: ", rule.path()));
|
||||
}
|
||||
// For a non-repeated field, the field value is stored only in the rule.
|
||||
@@ -280,7 +280,7 @@ class TemplateExpanderImpl {
|
||||
if (!status.ok()) break;
|
||||
std::vector<FieldValue> values;
|
||||
if (!ExpandTemplateRule(rules[i], base[0], &values)) {
|
||||
status = ::mediapipe::InternalError("ExpandTemplateRule failed");
|
||||
status = mediapipe::InternalError("ExpandTemplateRule failed");
|
||||
break;
|
||||
}
|
||||
edits.push_back(values);
|
||||
@@ -348,7 +348,7 @@ class TemplateExpanderImpl {
|
||||
// Retrieve the var param and the range expression.
|
||||
const TemplateExpression& rule = template_rules_.rule().Get(base_index);
|
||||
if (rule.arg().empty() || rule.arg().size() > 2) {
|
||||
RecordError(::mediapipe::InvalidArgumentError(
|
||||
RecordError(mediapipe::InvalidArgumentError(
|
||||
"Param declaration must specify a parameter name and "
|
||||
"may specify a single default value."));
|
||||
}
|
||||
@@ -401,7 +401,7 @@ class TemplateExpanderImpl {
|
||||
TemplateArgument* result = GetItem(&environment_, expr.param());
|
||||
if (result == nullptr) {
|
||||
RecordError(
|
||||
::mediapipe::NotFoundError(absl::StrCat("param: ", expr.param())));
|
||||
mediapipe::NotFoundError(absl::StrCat("param: ", expr.param())));
|
||||
return AsArgument(0.0);
|
||||
}
|
||||
return *result;
|
||||
@@ -412,7 +412,7 @@ class TemplateExpanderImpl {
|
||||
TemplateArgument lhs = EvalExpression(expr.arg(0));
|
||||
TemplateArgument* result = GetItem(lhs.mutable_dict(), expr.arg(1).param());
|
||||
if (result == nullptr) {
|
||||
RecordError(::mediapipe::NotFoundError(
|
||||
RecordError(mediapipe::NotFoundError(
|
||||
absl::StrCat("param field: ", expr.arg(1).param())));
|
||||
return AsArgument(0.0);
|
||||
}
|
||||
@@ -427,7 +427,7 @@ class TemplateExpanderImpl {
|
||||
}
|
||||
if (value.has_str()) {
|
||||
if (!absl::SimpleAtod(value.str(), &result)) {
|
||||
RecordError(::mediapipe::InvalidArgumentError(value.str()));
|
||||
RecordError(mediapipe::InvalidArgumentError(value.str()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -452,7 +452,7 @@ class TemplateExpanderImpl {
|
||||
return value.num() != 0;
|
||||
} else if (value.has_str()) {
|
||||
if (!absl::SimpleAtob(value.str(), &result)) {
|
||||
RecordError(::mediapipe::InvalidArgumentError(value.str()));
|
||||
RecordError(mediapipe::InvalidArgumentError(value.str()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -462,7 +462,7 @@ class TemplateExpanderImpl {
|
||||
TemplateArgument AsDict(const std::vector<TemplateArgument>& args) {
|
||||
TemplateArgument result;
|
||||
if (args.size() % 2 != 0) {
|
||||
RecordError(::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
RecordError(mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Dict requires an even number of arguments, got: ", args.size())));
|
||||
return result;
|
||||
}
|
||||
@@ -613,11 +613,11 @@ class TemplateExpanderImpl {
|
||||
result->push_back(r[0]);
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Record a Status if it indicates an error.
|
||||
void RecordError(const ::mediapipe::Status& status) {
|
||||
void RecordError(const mediapipe::Status& status) {
|
||||
if (!status.ok()) {
|
||||
errors_->push_back(status);
|
||||
}
|
||||
@@ -631,23 +631,23 @@ class TemplateExpanderImpl {
|
||||
TemplateDict environment_;
|
||||
|
||||
// List of errors found in template parameters.
|
||||
std::vector<::mediapipe::Status>* errors_;
|
||||
std::vector<mediapipe::Status>* errors_;
|
||||
};
|
||||
|
||||
TemplateExpander::TemplateExpander() {}
|
||||
|
||||
// Expands template rules within a proto message.
|
||||
// Replaces template rules with expanded sub-messages.
|
||||
::mediapipe::Status TemplateExpander::ExpandTemplates(
|
||||
mediapipe::Status TemplateExpander::ExpandTemplates(
|
||||
const TemplateDict& args, const CalculatorGraphTemplate& templ,
|
||||
CalculatorGraphConfig* output) {
|
||||
errors_.clear();
|
||||
TemplateExpanderImpl expander(&errors_);
|
||||
if (!expander.ExpandTemplates(args, templ, output)) {
|
||||
errors_.push_back(::mediapipe::InternalError("ExpandTemplates failed"));
|
||||
errors_.push_back(mediapipe::InternalError("ExpandTemplates failed"));
|
||||
}
|
||||
::mediapipe::Status status;
|
||||
for (const ::mediapipe::Status& error : errors_) {
|
||||
mediapipe::Status status;
|
||||
for (const mediapipe::Status& error : errors_) {
|
||||
LOG(ERROR) << error;
|
||||
status.Update(error);
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ class TemplateExpander {
|
||||
// Applies the rules specified in a CalculatorGraphTemplate to a
|
||||
// CalculatorGraphConfig. Each rule references a nested field-value or
|
||||
// message and defines zero or more replacement values for it.
|
||||
::mediapipe::Status ExpandTemplates(const TemplateDict& args,
|
||||
const CalculatorGraphTemplate& templ,
|
||||
CalculatorGraphConfig* output);
|
||||
mediapipe::Status ExpandTemplates(const TemplateDict& args,
|
||||
const CalculatorGraphTemplate& templ,
|
||||
CalculatorGraphConfig* output);
|
||||
|
||||
private:
|
||||
// List of errors found in template parameters.
|
||||
std::vector<::mediapipe::Status> errors_;
|
||||
std::vector<mediapipe::Status> errors_;
|
||||
};
|
||||
|
||||
} // namespace tool
|
||||
|
||||
@@ -1332,13 +1332,13 @@ bool IsFunctionOperator(const std::string& token) {
|
||||
// by the DynamicMessageFactory ("output"). These two Messages have
|
||||
// different Descriptors so Message::MergeFrom cannot be applied directly,
|
||||
// but they are expected to be equivalent.
|
||||
::mediapipe::Status MergeFields(const Message& source, Message* dest) {
|
||||
mediapipe::Status MergeFields(const Message& source, Message* dest) {
|
||||
std::unique_ptr<Message> temp(dest->New());
|
||||
std::string temp_str;
|
||||
RET_CHECK(TextFormat::PrintToString(source, &temp_str));
|
||||
RET_CHECK(TextFormat::ParseFromString(temp_str, temp.get()));
|
||||
dest->MergeFrom(*temp);
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Returns the (tag, index) pairs in a field path.
|
||||
@@ -1356,7 +1356,7 @@ mediapipe::Status ProtoPathSplit(const std::string& path,
|
||||
bool ok = absl::SimpleAtoi(id_pair.first, &tag) &&
|
||||
absl::SimpleAtoi(id_pair.second, &index);
|
||||
if (!ok) {
|
||||
status.Update(::mediapipe::InvalidArgumentError(path));
|
||||
status.Update(mediapipe::InvalidArgumentError(path));
|
||||
}
|
||||
result->push_back(std::make_pair(tag, index));
|
||||
}
|
||||
|
||||
@@ -99,11 +99,11 @@ int main(int argc, char** argv) {
|
||||
mediapipe::Status status;
|
||||
if (FLAGS_proto_source.empty()) {
|
||||
status.Update(
|
||||
::mediapipe::InvalidArgumentError("--proto_source must be specified"));
|
||||
mediapipe::InvalidArgumentError("--proto_source must be specified"));
|
||||
}
|
||||
if (FLAGS_proto_output.empty()) {
|
||||
status.Update(
|
||||
::mediapipe::InvalidArgumentError("--proto_output must be specified"));
|
||||
mediapipe::InvalidArgumentError("--proto_output must be specified"));
|
||||
}
|
||||
if (!status.ok()) {
|
||||
return EXIT_FAILURE;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace mediapipe {
|
||||
|
||||
namespace tool {
|
||||
|
||||
::mediapipe::Status ValidateInput(const InputCollection& input_collection) {
|
||||
mediapipe::Status ValidateInput(const InputCollection& input_collection) {
|
||||
if (!input_collection.name().empty()) {
|
||||
MP_RETURN_IF_ERROR(tool::ValidateName(input_collection.name())).SetPrepend()
|
||||
<< "InputCollection " << input_collection.name()
|
||||
@@ -34,14 +34,14 @@ namespace tool {
|
||||
}
|
||||
if (input_collection.input_type() <= InputCollection::UNKNOWN ||
|
||||
input_collection.input_type() >= InputCollection::INVALID_UPPER_BOUND) {
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"InputCollection must specify a valid input_type.");
|
||||
}
|
||||
if (input_collection.file_name().empty()) {
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
"InputCollection must specify a file_name.");
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
|
||||
@@ -24,12 +24,12 @@ namespace mediapipe {
|
||||
|
||||
namespace tool {
|
||||
|
||||
// Returns ::mediapipe::OkStatus() if the InputCollection is valid. An input
|
||||
// Returns mediapipe::OkStatus() if the InputCollection is valid. An input
|
||||
// collection is invalid if it does not have the proper fields set
|
||||
// depending on what its input_type field is. Furthermore, if it uses
|
||||
// INLINE, then the number of value fields in each inputs must match
|
||||
// the number of input_side_packet_name fields.
|
||||
::mediapipe::Status ValidateInput(const InputCollection& input);
|
||||
mediapipe::Status ValidateInput(const InputCollection& input);
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace tool {
|
||||
#define MEDIAPIPE_TAG_INDEX_REGEX \
|
||||
"(" MEDIAPIPE_TAG_REGEX ")?(:" MEDIAPIPE_NUMBER_REGEX ")?"
|
||||
|
||||
::mediapipe::Status GetTagAndNameInfo(
|
||||
mediapipe::Status GetTagAndNameInfo(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& tags_and_names,
|
||||
TagAndNameInfo* info) {
|
||||
RET_CHECK(info);
|
||||
@@ -59,15 +59,15 @@ namespace tool {
|
||||
if (info->tags.size() > 0 && info->names.size() != info->tags.size()) {
|
||||
info->tags.clear();
|
||||
info->names.clear();
|
||||
return ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
return mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Each set of names must use exclusively either tags or indexes. "
|
||||
"Encountered: \"",
|
||||
absl::StrJoin(tags_and_names, "\", \""), "\""));
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status SetFromTagAndNameInfo(
|
||||
mediapipe::Status SetFromTagAndNameInfo(
|
||||
const TagAndNameInfo& info,
|
||||
proto_ns::RepeatedPtrField<ProtoString>* tags_and_names) {
|
||||
tags_and_names->Clear();
|
||||
@@ -78,7 +78,7 @@ namespace tool {
|
||||
}
|
||||
} else {
|
||||
if (info.names.size() != info.tags.size()) {
|
||||
return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Number of tags " << info.names.size()
|
||||
<< " does not match the number of tags " << info.tags.size();
|
||||
}
|
||||
@@ -88,52 +88,52 @@ namespace tool {
|
||||
*tags_and_names->Add() = absl::StrCat(info.tags[i], ":", info.names[i]);
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ValidateName(const std::string& name) {
|
||||
mediapipe::Status ValidateName(const std::string& name) {
|
||||
return name.length() > 0 && (name[0] == '_' || islower(name[0])) &&
|
||||
std::all_of(name.begin() + 1, name.end(),
|
||||
[](char c) {
|
||||
return c == '_' || isdigit(c) || islower(c);
|
||||
})
|
||||
? ::mediapipe::OkStatus()
|
||||
: ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
? mediapipe::OkStatus()
|
||||
: mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Name \"", absl::CEscape(name),
|
||||
"\" does not match \"" MEDIAPIPE_NAME_REGEX "\"."));
|
||||
}
|
||||
|
||||
::mediapipe::Status ValidateNumber(const std::string& number) {
|
||||
mediapipe::Status ValidateNumber(const std::string& number) {
|
||||
return (number.length() == 1 && isdigit(number[0])) ||
|
||||
(number.length() > 1 && isdigit(number[0]) &&
|
||||
number[0] != '0' &&
|
||||
std::all_of(number.begin() + 1, number.end(),
|
||||
[](char c) { return isdigit(c); }))
|
||||
? ::mediapipe::OkStatus()
|
||||
: ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
? mediapipe::OkStatus()
|
||||
: mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Number \"", absl::CEscape(number),
|
||||
"\" does not match \"" MEDIAPIPE_NUMBER_REGEX "\"."));
|
||||
}
|
||||
|
||||
::mediapipe::Status ValidateTag(const std::string& tag) {
|
||||
mediapipe::Status ValidateTag(const std::string& tag) {
|
||||
return tag.length() > 0 && (tag[0] == '_' || isupper(tag[0])) &&
|
||||
std::all_of(tag.begin() + 1, tag.end(),
|
||||
[](char c) {
|
||||
return c == '_' || isdigit(c) || isupper(c);
|
||||
})
|
||||
? ::mediapipe::OkStatus()
|
||||
: ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
? mediapipe::OkStatus()
|
||||
: mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"Tag \"", absl::CEscape(tag),
|
||||
"\" does not match \"" MEDIAPIPE_TAG_REGEX "\"."));
|
||||
}
|
||||
|
||||
::mediapipe::Status ParseTagAndName(const std::string& tag_and_name,
|
||||
std::string* tag, std::string* name) {
|
||||
mediapipe::Status ParseTagAndName(const std::string& tag_and_name,
|
||||
std::string* tag, std::string* name) {
|
||||
// An optional tag and colon, followed by a name.
|
||||
RET_CHECK(tag);
|
||||
RET_CHECK(name);
|
||||
::mediapipe::Status tag_status = ::mediapipe::OkStatus();
|
||||
::mediapipe::Status name_status = ::mediapipe::UnknownError("");
|
||||
mediapipe::Status tag_status = mediapipe::OkStatus();
|
||||
mediapipe::Status name_status = mediapipe::UnknownError("");
|
||||
int name_index = 0;
|
||||
std::vector<std::string> v = absl::StrSplit(tag_and_name, ':');
|
||||
if (v.size() == 1) {
|
||||
@@ -144,11 +144,11 @@ namespace tool {
|
||||
name_status = ValidateName(v[1]);
|
||||
name_index = 1;
|
||||
}
|
||||
if (name_index == -1 || tag_status != ::mediapipe::OkStatus() ||
|
||||
name_status != ::mediapipe::OkStatus()) {
|
||||
if (name_index == -1 || tag_status != mediapipe::OkStatus() ||
|
||||
name_status != mediapipe::OkStatus()) {
|
||||
tag->clear();
|
||||
name->clear();
|
||||
return ::mediapipe::InvalidArgumentError(
|
||||
return mediapipe::InvalidArgumentError(
|
||||
absl::StrCat("\"tag and name\" is invalid, \"", tag_and_name,
|
||||
"\" does not match "
|
||||
"\"" MEDIAPIPE_TAG_AND_NAME_REGEX
|
||||
@@ -156,20 +156,20 @@ namespace tool {
|
||||
}
|
||||
*tag = name_index == 1 ? v[0] : "";
|
||||
*name = v[name_index];
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ParseTagIndexName(const std::string& tag_index_name,
|
||||
std::string* tag, int* index,
|
||||
std::string* name) {
|
||||
mediapipe::Status ParseTagIndexName(const std::string& tag_index_name,
|
||||
std::string* tag, int* index,
|
||||
std::string* name) {
|
||||
// An optional tag and colon, an optional index and color, followed by a name.
|
||||
RET_CHECK(tag);
|
||||
RET_CHECK(index);
|
||||
RET_CHECK(name);
|
||||
|
||||
::mediapipe::Status tag_status = ::mediapipe::OkStatus();
|
||||
::mediapipe::Status number_status = ::mediapipe::OkStatus();
|
||||
::mediapipe::Status name_status = ::mediapipe::UnknownError("");
|
||||
mediapipe::Status tag_status = mediapipe::OkStatus();
|
||||
mediapipe::Status number_status = mediapipe::OkStatus();
|
||||
mediapipe::Status name_status = mediapipe::UnknownError("");
|
||||
int name_index = -1;
|
||||
int the_index = 0;
|
||||
std::vector<std::string> v = absl::StrSplit(tag_index_name, ':');
|
||||
@@ -195,7 +195,7 @@ namespace tool {
|
||||
} // else omitted, name_index == -1, triggering error.
|
||||
if (name_index == -1 || !tag_status.ok() || !number_status.ok() ||
|
||||
!name_status.ok()) {
|
||||
return ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
return mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"TAG:index:name is invalid, \"", tag_index_name,
|
||||
"\" does not match "
|
||||
"\"" MEDIAPIPE_TAG_INDEX_NAME_REGEX
|
||||
@@ -204,16 +204,16 @@ namespace tool {
|
||||
*tag = name_index != 0 ? v[0] : "";
|
||||
*index = the_index;
|
||||
*name = v[name_index];
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status ParseTagIndex(const std::string& tag_index,
|
||||
std::string* tag, int* index) {
|
||||
mediapipe::Status ParseTagIndex(const std::string& tag_index, std::string* tag,
|
||||
int* index) {
|
||||
RET_CHECK(tag);
|
||||
RET_CHECK(index);
|
||||
|
||||
::mediapipe::Status tag_status = ::mediapipe::OkStatus();
|
||||
::mediapipe::Status number_status = ::mediapipe::OkStatus();
|
||||
mediapipe::Status tag_status = mediapipe::OkStatus();
|
||||
mediapipe::Status number_status = mediapipe::OkStatus();
|
||||
int the_index = -1;
|
||||
std::vector<std::string> v = absl::StrSplit(tag_index, ':');
|
||||
if (v.size() == 1) {
|
||||
@@ -234,14 +234,14 @@ namespace tool {
|
||||
}
|
||||
} // else omitted, the_index == -1, triggering error.
|
||||
if (the_index == -1 || !tag_status.ok() || !number_status.ok()) {
|
||||
return ::mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
return mediapipe::InvalidArgumentError(absl::StrCat(
|
||||
"TAG:index is invalid, \"", tag_index,
|
||||
"\" does not match "
|
||||
"\"" MEDIAPIPE_TAG_INDEX_REGEX "\" (examples: \"TAG\" \"VIDEO:2\")."));
|
||||
}
|
||||
*tag = v[0];
|
||||
*index = the_index;
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
#undef MEDIAPIPE_NAME_REGEX
|
||||
|
||||
@@ -52,7 +52,7 @@ ABSL_DEPRECATED(
|
||||
"support the TAG:INDEX:name notation. You can use Create() to create the "
|
||||
"tag map, and then Names(), Mapping(), and other methods to access the "
|
||||
"tag, index and name information.")
|
||||
::mediapipe::Status GetTagAndNameInfo(
|
||||
mediapipe::Status GetTagAndNameInfo(
|
||||
const proto_ns::RepeatedPtrField<ProtoString>& tags_and_names,
|
||||
TagAndNameInfo* info);
|
||||
|
||||
@@ -62,7 +62,7 @@ ABSL_DEPRECATED(
|
||||
"Prefer using mediapipe::tool::TagMap instead, since this method does not "
|
||||
"support the TAG:INDEX:name notation. You can use CanonicalEntries() to "
|
||||
"translate a tag map to a RepeatedPtrField of tag and names.")
|
||||
::mediapipe::Status SetFromTagAndNameInfo(
|
||||
mediapipe::Status SetFromTagAndNameInfo(
|
||||
const TagAndNameInfo& info,
|
||||
proto_ns::RepeatedPtrField<ProtoString>* tags_and_names);
|
||||
|
||||
@@ -76,17 +76,17 @@ ABSL_DEPRECATED(
|
||||
// trainer/calculator names.
|
||||
// (3) Because input side packet names end up in model directory names,
|
||||
// where lower case naming is the norm.
|
||||
::mediapipe::Status ValidateName(const std::string& name);
|
||||
mediapipe::Status ValidateName(const std::string& name);
|
||||
// The std::string is a valid tag name. Tags use only upper case letters,
|
||||
// numbers, and underscores.
|
||||
::mediapipe::Status ValidateTag(const std::string& tag);
|
||||
mediapipe::Status ValidateTag(const std::string& tag);
|
||||
|
||||
// Parse a "Tag and Name" std::string into a tag and a name.
|
||||
// The format is an optional tag and colon, followed by a name.
|
||||
// Example 1: "VIDEO:frames2" -> tag: "VIDEO", name: "frames2"
|
||||
// Example 2: "video_frames_1" -> tag: "", name: "video_frames_1"
|
||||
::mediapipe::Status ParseTagAndName(const std::string& tag_and_name,
|
||||
std::string* tag, std::string* name);
|
||||
mediapipe::Status ParseTagAndName(const std::string& tag_and_name,
|
||||
std::string* tag, std::string* name);
|
||||
|
||||
// Parse a generic TAG:index:name std::string. The format is a tag, then an
|
||||
// index, then a name. The tag and index are optional. If the index
|
||||
@@ -96,9 +96,9 @@ ABSL_DEPRECATED(
|
||||
// "VIDEO:frames2" -> tag: "VIDEO", index: 0, name: "frames2"
|
||||
// "VIDEO:1:frames" -> tag: "VIDEO", index: 1, name: "frames"
|
||||
// "raw_frames" -> tag: "", index: -1, name: "raw_frames"
|
||||
::mediapipe::Status ParseTagIndexName(const std::string& tag_and_name,
|
||||
std::string* tag, int* index,
|
||||
std::string* name);
|
||||
mediapipe::Status ParseTagIndexName(const std::string& tag_and_name,
|
||||
std::string* tag, int* index,
|
||||
std::string* name);
|
||||
|
||||
// Parse a generic TAG:index std::string. The format is a tag, then an index
|
||||
// with both being optional. If the tag is missing it is assumed to be
|
||||
@@ -109,8 +109,8 @@ ABSL_DEPRECATED(
|
||||
// "VIDEO:1" -> tag: "VIDEO", index: 1
|
||||
// ":2" -> tag: "", index: 2
|
||||
// "" -> tag: "", index: 0
|
||||
::mediapipe::Status ParseTagIndex(const std::string& tag_and_index,
|
||||
std::string* tag, int* index);
|
||||
mediapipe::Status ParseTagIndex(const std::string& tag_and_index,
|
||||
std::string* tag, int* index);
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -207,9 +207,8 @@ TEST(ValidateNameTest, ParseTagIndexName) {
|
||||
"mieko_harada");
|
||||
TestPassParseTagIndexName("A1:100:mieko1", "A1", 100, "mieko1");
|
||||
TestPassParseTagIndexName(
|
||||
absl::StrCat("A1:", ::mediapipe::internal::kMaxCollectionItemId,
|
||||
":mieko1"),
|
||||
"A1", ::mediapipe::internal::kMaxCollectionItemId, "mieko1");
|
||||
absl::StrCat("A1:", mediapipe::internal::kMaxCollectionItemId, ":mieko1"),
|
||||
"A1", mediapipe::internal::kMaxCollectionItemId, "mieko1");
|
||||
|
||||
// Failure cases.
|
||||
TestFailParseTagIndexName(""); // Empty name.
|
||||
@@ -246,7 +245,7 @@ TEST(ValidateNameTest, ParseTagIndexName) {
|
||||
TestFailParseTagIndexName("A:01:name"); // Leading zero.
|
||||
TestFailParseTagIndexName("A:00:name"); // Leading zero.
|
||||
TestFailParseTagIndexName(
|
||||
absl::StrCat("A:", ::mediapipe::internal::kMaxCollectionItemId + 1,
|
||||
absl::StrCat("A:", mediapipe::internal::kMaxCollectionItemId + 1,
|
||||
":a")); // Too large an index.
|
||||
// Extra field
|
||||
TestFailParseTagIndexName("A:1:a:"); // extra field.
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace mediapipe {
|
||||
|
||||
namespace tool {
|
||||
::mediapipe::Status RunGeneratorFillExpectations(
|
||||
mediapipe::Status RunGeneratorFillExpectations(
|
||||
const PacketGeneratorConfig& input_config, const std::string& package) {
|
||||
// TODO Remove conversion after everyone uses input/output
|
||||
// side packet.
|
||||
@@ -64,7 +64,7 @@ namespace tool {
|
||||
}
|
||||
|
||||
// Check that everything got initialized.
|
||||
std::vector<::mediapipe::Status> statuses;
|
||||
std::vector<mediapipe::Status> statuses;
|
||||
statuses.push_back(ValidatePacketTypeSet(contract.InputSidePackets()));
|
||||
statuses.push_back(ValidatePacketTypeSet(contract.OutputSidePackets()));
|
||||
return tool::CombinedStatus(
|
||||
@@ -72,7 +72,7 @@ namespace tool {
|
||||
statuses);
|
||||
}
|
||||
|
||||
::mediapipe::Status RunGenerateAndValidateTypes(
|
||||
mediapipe::Status RunGenerateAndValidateTypes(
|
||||
const std::string& packet_generator_name,
|
||||
const PacketGeneratorOptions& extendable_options,
|
||||
const PacketSet& input_side_packets, PacketSet* output_side_packets,
|
||||
@@ -95,7 +95,7 @@ namespace tool {
|
||||
.SetPrepend()
|
||||
<< packet_generator_name << "::FillExpectations failed: ";
|
||||
// Check that the types were filled well.
|
||||
std::vector<::mediapipe::Status> statuses;
|
||||
std::vector<mediapipe::Status> statuses;
|
||||
statuses.push_back(ValidatePacketTypeSet(input_side_packet_types));
|
||||
statuses.push_back(ValidatePacketTypeSet(output_side_packet_types));
|
||||
MP_RETURN_IF_ERROR(tool::CombinedStatus(
|
||||
@@ -118,7 +118,7 @@ namespace tool {
|
||||
<< packet_generator_name
|
||||
<< "::FillExpectations expected different "
|
||||
"output type than those produced: ";
|
||||
return ::mediapipe::OkStatus();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
|
||||
@@ -26,14 +26,14 @@ namespace mediapipe {
|
||||
|
||||
namespace tool {
|
||||
// Equivalent functions for PacketGenerators.
|
||||
::mediapipe::Status RunGeneratorFillExpectations(
|
||||
mediapipe::Status RunGeneratorFillExpectations(
|
||||
const PacketGeneratorConfig& config,
|
||||
const std::string& package = "mediapipe");
|
||||
|
||||
// Run PacketGenerator::Generate() on the given generator, options,
|
||||
// and inputs to produce outputs. Validate the types of the inputs and
|
||||
// outputs using PacketGenerator::FillExpectations.
|
||||
::mediapipe::Status RunGenerateAndValidateTypes(
|
||||
mediapipe::Status RunGenerateAndValidateTypes(
|
||||
const std::string& packet_generator_name,
|
||||
const PacketGeneratorOptions& extendable_options,
|
||||
const PacketSet& input_side_packets, PacketSet* output_side_packets,
|
||||
|
||||
Reference in New Issue
Block a user