Project import generated by Copybara.

GitOrigin-RevId: d8caa66de45839696f5bd0786ad3bfbcb9cff632
This commit is contained in:
MediaPipe Team
2020-12-09 22:43:33 -05:00
committed by chuoling
parent f15da632de
commit 2b58cceec9
750 changed files with 22901 additions and 9478 deletions
+117
View File
@@ -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
+31
View File
@@ -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_
+5 -5
View File
@@ -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 "
+1 -1
View File
@@ -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;
}
+4 -2
View File
@@ -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,
+1 -1
View File
@@ -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_
+1 -1
View File
@@ -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);
}
+49 -51
View File
@@ -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
+8 -7
View File
@@ -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.
+25 -26
View File
@@ -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);
+6 -6
View File
@@ -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_;
+7 -7
View File
@@ -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"
+6 -6
View File
@@ -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.");
}
+20 -21
View File
@@ -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;
+11 -11
View File
@@ -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
+20 -20
View File
@@ -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
+24 -24
View File
@@ -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
+7 -7
View File
@@ -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 {
+4 -4
View File
@@ -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(
+3 -3
View File
@@ -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) {
+3 -3
View File
@@ -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
+5 -5
View File
@@ -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();
+20 -20
View File
@@ -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);
}
+4 -4
View File
@@ -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
+3 -3
View File
@@ -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;
+4 -4
View File
@@ -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
+2 -2
View File
@@ -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
+37 -37
View File
@@ -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
+11 -11
View File
@@ -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.
+5 -5
View File
@@ -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
+2 -2
View File
@@ -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,