Project import generated by Copybara.
GitOrigin-RevId: 373e3ac1e5839befd95bf7d73ceff3c5f1171969
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#if !MEDIAPIPE_DISABLE_GPU
|
||||
#ifdef __APPLE__
|
||||
#include "mediapipe/objc/CFHolder.h"
|
||||
#include "mediapipe/objc/util.h"
|
||||
#endif // __APPLE__
|
||||
#endif // !MEDIAPIPE_DISABLE_GPU
|
||||
|
||||
|
||||
@@ -89,6 +89,18 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "commandlineflags",
|
||||
hdrs = [
|
||||
"commandlineflags.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//third_party:glog",
|
||||
"@com_google_absl//absl/flags:flag",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "core_proto",
|
||||
hdrs = [
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
#ifndef MEDIAPIPE_PORT_COMMANDLINEFLAGS_H_
|
||||
#define MEDIAPIPE_PORT_COMMANDLINEFLAGS_H_
|
||||
|
||||
#include "gflags/gflags.h"
|
||||
namespace absl {
|
||||
template <typename T>
|
||||
T GetFlag(const T& f) {
|
||||
return f;
|
||||
}
|
||||
template <typename T, typename U>
|
||||
void SetFlag(T* f, const U& u) {
|
||||
*f = u;
|
||||
}
|
||||
} // namespace absl
|
||||
|
||||
#endif // MEDIAPIPE_PORT_COMMANDLINEFLAGS_H_
|
||||
@@ -202,6 +202,7 @@ cc_library(
|
||||
"//mediapipe/framework:packet_type",
|
||||
"//mediapipe/framework/port:advanced_proto",
|
||||
"//mediapipe/framework/port:any_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings",
|
||||
@@ -291,7 +292,9 @@ mediapipe_cc_test(
|
||||
data = [":node_chain_subgraph.proto"],
|
||||
requires_full_emulation = False,
|
||||
deps = [
|
||||
":options_field_util",
|
||||
":options_registry",
|
||||
":options_syntax_util",
|
||||
":options_util",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator_cc_proto",
|
||||
@@ -305,8 +308,8 @@ mediapipe_cc_test(
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/testdata:night_light_calculator_options_lib",
|
||||
"//mediapipe/framework/tool:node_chain_subgraph_options_lib",
|
||||
"//mediapipe/framework/tool:options_syntax_util",
|
||||
"//mediapipe/util:header_util",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "mediapipe/framework/packet.h"
|
||||
#include "mediapipe/framework/packet_type.h"
|
||||
#include "mediapipe/framework/port/advanced_proto_inc.h"
|
||||
#include "mediapipe/framework/port/any_proto.h"
|
||||
#include "mediapipe/framework/port/canonical_errors.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/tool/name_util.h"
|
||||
#include "mediapipe/framework/tool/proto_util_lite.h"
|
||||
@@ -31,6 +33,9 @@ using ::mediapipe::proto_ns::io::StringOutputStream;
|
||||
// Utility functions for OptionsFieldUtil.
|
||||
namespace {
|
||||
|
||||
// The type name for the proto3 "Any" type.
|
||||
constexpr absl::string_view kGoogleProtobufAny = "google.protobuf.Any";
|
||||
|
||||
// Converts a FieldDescriptor::Type to the corresponding FieldType.
|
||||
FieldType AsFieldType(proto_ns::FieldDescriptorProto::Type type) {
|
||||
return static_cast<FieldType>(type);
|
||||
@@ -81,7 +86,7 @@ absl::Status WriteValue(const FieldData& value, FieldType field_type,
|
||||
return absl::UnimplementedError(
|
||||
absl::StrCat("Cannot write type: ", field_type));
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Serializes a packet value.
|
||||
@@ -167,6 +172,7 @@ absl::Status ReadValue(absl::string_view field_bytes, FieldType field_type,
|
||||
// Deserializes a packet from a protobuf field.
|
||||
absl::Status ReadField(absl::string_view bytes, const FieldDescriptor* field,
|
||||
FieldData* result) {
|
||||
RET_CHECK_NE(field, nullptr);
|
||||
FieldType field_type = AsFieldType(field->type());
|
||||
std::string message_type = (field_type == WireFormatLite::TYPE_MESSAGE)
|
||||
? field->message_type()->full_name()
|
||||
@@ -174,47 +180,137 @@ absl::Status ReadField(absl::string_view bytes, const FieldDescriptor* field,
|
||||
return ReadValue(bytes, field_type, message_type, result);
|
||||
}
|
||||
|
||||
// Converts a chain of fields and indexes into field-numbers and indexes.
|
||||
ProtoUtilLite::ProtoPath AsProtoPath(const FieldPath& field_path) {
|
||||
ProtoUtilLite::ProtoPath result;
|
||||
for (auto field : field_path) {
|
||||
result.push_back({field.first->number(), field.second});
|
||||
// Reads all values from a repeated field.
|
||||
absl::Status GetFieldValues(const FieldData& message_data,
|
||||
const FieldDescriptor& field,
|
||||
std::vector<FieldData>* result) {
|
||||
const std::string& message_bytes = message_data.message_value().value();
|
||||
FieldType field_type = AsFieldType(field.type());
|
||||
ProtoUtilLite proto_util;
|
||||
ProtoUtilLite::ProtoPath proto_path = {{field.number(), 0}};
|
||||
int count;
|
||||
MP_RETURN_IF_ERROR(
|
||||
proto_util.GetFieldCount(message_bytes, proto_path, field_type, &count));
|
||||
std::vector<std::string> field_values;
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldRange(message_bytes, proto_path, count,
|
||||
field_type, &field_values));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
FieldData r;
|
||||
MP_RETURN_IF_ERROR(ReadField(field_values[i], &field, &r));
|
||||
result->push_back(std::move(r));
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Reads one value from a field.
|
||||
absl::Status GetFieldValue(const FieldData& message_data,
|
||||
const FieldPathEntry& entry, FieldData* result) {
|
||||
RET_CHECK_NE(entry.field, nullptr);
|
||||
const std::string& message_bytes = message_data.message_value().value();
|
||||
FieldType field_type = AsFieldType(entry.field->type());
|
||||
ProtoUtilLite proto_util;
|
||||
ProtoUtilLite::ProtoPath proto_path = {{entry.field->number(), entry.index}};
|
||||
std::vector<std::string> field_values;
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldRange(message_bytes, proto_path, 1,
|
||||
field_type, &field_values));
|
||||
MP_RETURN_IF_ERROR(ReadField(field_values[0], entry.field, result));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Writes one value to a field.
|
||||
absl::Status SetFieldValue(const FieldPathEntry& entry, const FieldData& value,
|
||||
FieldData* result) {
|
||||
std::vector<FieldData> field_values;
|
||||
ProtoUtilLite proto_util;
|
||||
FieldType field_type = AsFieldType(entry.field->type());
|
||||
ProtoUtilLite::ProtoPath proto_path = {{entry.field->number(), entry.index}};
|
||||
std::string* message_bytes = result->mutable_message_value()->mutable_value();
|
||||
int field_count;
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldCount(*message_bytes, proto_path,
|
||||
field_type, &field_count));
|
||||
if (entry.index > field_count) {
|
||||
return absl::OutOfRangeError(
|
||||
absl::StrCat("Option field index out of range: ", entry.index));
|
||||
}
|
||||
int replace_length = entry.index < field_count ? 1 : 0;
|
||||
std::string field_value;
|
||||
MP_RETURN_IF_ERROR(WriteField(value, entry.field, &field_value));
|
||||
MP_RETURN_IF_ERROR(proto_util.ReplaceFieldRange(
|
||||
message_bytes, proto_path, replace_length, field_type, {field_value}));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Returns true for a field of type "google.protobuf.Any".
|
||||
bool IsProtobufAny(const FieldDescriptor* field) {
|
||||
return AsFieldType(field->type()) == FieldType::TYPE_MESSAGE &&
|
||||
field->message_type()->full_name() == kGoogleProtobufAny;
|
||||
}
|
||||
|
||||
// Returns the message FieldData from a serialized protobuf.Any.
|
||||
FieldData ParseProtobufAny(const FieldData& data) {
|
||||
protobuf::Any any;
|
||||
any.ParseFromString(data.message_value().value());
|
||||
FieldData result;
|
||||
result.mutable_message_value()->set_value(std::string(any.value()));
|
||||
result.mutable_message_value()->set_type_url(any.type_url());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the options protobuf for a subgraph.
|
||||
// TODO: Ensure that this works with multiple options protobufs.
|
||||
absl::Status GetOptionsMessage(
|
||||
const proto_ns::RepeatedPtrField<mediapipe::protobuf::Any>& options_any,
|
||||
const proto_ns::MessageLite& options_ext, FieldData* result) {
|
||||
// Read the "graph_options" or "node_options" field.
|
||||
for (const auto& options : options_any) {
|
||||
if (options.type_url().empty()) {
|
||||
continue;
|
||||
}
|
||||
result->mutable_message_value()->set_type_url(options.type_url());
|
||||
result->mutable_message_value()->set_value(std::string(options.value()));
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
// Returns the serialized protobuf.Any containing a message FieldData.
|
||||
FieldData SerializeProtobufAny(const FieldData& data) {
|
||||
protobuf::Any any;
|
||||
any.set_value(data.message_value().value());
|
||||
any.set_type_url(data.message_value().type_url());
|
||||
FieldData result;
|
||||
result.mutable_message_value()->set_value(any.SerializeAsString());
|
||||
result.mutable_message_value()->set_type_url(TypeUrl(kGoogleProtobufAny));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read the "options" field.
|
||||
FieldData message_data;
|
||||
*message_data.mutable_message_value()->mutable_value() =
|
||||
options_ext.SerializeAsString();
|
||||
message_data.mutable_message_value()->set_type_url(options_ext.GetTypeName());
|
||||
std::vector<const FieldDescriptor*> ext_fields;
|
||||
OptionsRegistry::FindAllExtensions(options_ext.GetTypeName(), &ext_fields);
|
||||
for (auto ext_field : ext_fields) {
|
||||
absl::Status status = GetField({{ext_field, 0}}, message_data, result);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
if (result->has_message_value()) {
|
||||
return status;
|
||||
// Returns the field index of an extension type in a repeated field.
|
||||
StatusOr<int> FindExtensionIndex(const FieldData& message_data,
|
||||
FieldPathEntry* entry) {
|
||||
if (entry->field == nullptr || !IsProtobufAny(entry->field)) {
|
||||
return -1;
|
||||
}
|
||||
std::string& extension_type = entry->extension_type;
|
||||
std::vector<FieldData> field_values;
|
||||
RET_CHECK_NE(entry->field, nullptr);
|
||||
MP_RETURN_IF_ERROR(
|
||||
GetFieldValues(message_data, *entry->field, &field_values));
|
||||
for (int i = 0; i < field_values.size(); ++i) {
|
||||
FieldData extension = ParseProtobufAny(field_values[i]);
|
||||
if (extension_type == "*" ||
|
||||
ParseTypeUrl(extension.message_value().type_url()) == extension_type) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Returns true if the value of a field is available.
|
||||
bool HasField(const FieldPath& field_path, const FieldData& message_data) {
|
||||
FieldData value;
|
||||
return GetField(field_path, message_data, &value).ok() &&
|
||||
value.value_case() != mediapipe::FieldData::VALUE_NOT_SET;
|
||||
}
|
||||
|
||||
// Returns the extension field containing the specified extension-type.
|
||||
const FieldDescriptor* FindExtensionField(const FieldData& message_data,
|
||||
absl::string_view extension_type) {
|
||||
std::string message_type =
|
||||
ParseTypeUrl(message_data.message_value().type_url());
|
||||
std::vector<const FieldDescriptor*> extensions;
|
||||
OptionsRegistry::FindAllExtensions(message_type, &extensions);
|
||||
for (const FieldDescriptor* extension : extensions) {
|
||||
if (extension->message_type()->full_name() == extension_type) {
|
||||
return extension;
|
||||
}
|
||||
if (extension_type == "*" && HasField({{extension, 0}}, message_data)) {
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Sets a protobuf in a repeated protobuf::Any field.
|
||||
@@ -234,6 +330,20 @@ void SetOptionsMessage(
|
||||
*options_any->mutable_value() = node_options.message_value().value();
|
||||
}
|
||||
|
||||
// Returns the count of values in a repeated field.
|
||||
int FieldCount(const FieldData& message_data, const FieldDescriptor* field) {
|
||||
const std::string& message_bytes = message_data.message_value().value();
|
||||
FieldType field_type = AsFieldType(field->type());
|
||||
ProtoUtilLite proto_util;
|
||||
ProtoUtilLite::ProtoPath proto_path = {{field->number(), 0}};
|
||||
int count;
|
||||
if (proto_util.GetFieldCount(message_bytes, proto_path, field_type, &count)
|
||||
.ok()) {
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Deserializes a packet containing a MessageLite value.
|
||||
@@ -247,8 +357,8 @@ absl::Status ReadMessage(const std::string& value, const std::string& type_name,
|
||||
}
|
||||
|
||||
// Merge two options FieldData values.
|
||||
absl::Status MergeOptionsMessages(const FieldData& base, const FieldData& over,
|
||||
FieldData* result) {
|
||||
absl::Status MergeMessages(const FieldData& base, const FieldData& over,
|
||||
FieldData* result) {
|
||||
absl::Status status;
|
||||
if (over.value_case() == FieldData::VALUE_NOT_SET) {
|
||||
*result = base;
|
||||
@@ -278,28 +388,148 @@ absl::Status MergeOptionsMessages(const FieldData& base, const FieldData& over,
|
||||
return status;
|
||||
}
|
||||
|
||||
// Returns either the extension field or the repeated protobuf.Any field index
|
||||
// holding the specified extension-type.
|
||||
absl::Status FindExtension(const FieldData& message_data,
|
||||
FieldPathEntry* entry) {
|
||||
if (entry->extension_type.empty()) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// For repeated protobuf::Any, find the index for the extension_type.
|
||||
ASSIGN_OR_RETURN(int index, FindExtensionIndex(message_data, entry));
|
||||
if (index != -1) {
|
||||
entry->index = index;
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Returns the extension field containing the specified extension-type.
|
||||
std::string& extension_type = entry->extension_type;
|
||||
const FieldDescriptor* field =
|
||||
FindExtensionField(message_data, extension_type);
|
||||
if (field != nullptr) {
|
||||
entry->field = field;
|
||||
entry->index = 0;
|
||||
return absl::OkStatus();
|
||||
}
|
||||
return absl::NotFoundError(
|
||||
absl::StrCat("Option extension not found: ", extension_type));
|
||||
}
|
||||
|
||||
// Return the FieldPath referencing an extension message.
|
||||
FieldPath GetExtensionPath(const std::string& parent_type,
|
||||
const std::string& extension_type,
|
||||
const std::string& field_name,
|
||||
bool is_protobuf_any) {
|
||||
FieldPath result;
|
||||
const tool::Descriptor* parent_descriptor =
|
||||
tool::OptionsRegistry::GetProtobufDescriptor(parent_type);
|
||||
FieldPathEntry field_entry;
|
||||
field_entry.field = parent_descriptor->FindFieldByName(field_name);
|
||||
if (is_protobuf_any) {
|
||||
field_entry.extension_type = extension_type;
|
||||
result = {std::move(field_entry)};
|
||||
} else {
|
||||
field_entry.index = 0;
|
||||
FieldPathEntry extension_entry;
|
||||
extension_entry.extension_type = extension_type;
|
||||
result = {std::move(field_entry), std::move(extension_entry)};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the requested options protobuf for a graph node.
|
||||
absl::Status GetNodeOptions(const FieldData& message_data,
|
||||
const std::string& extension_type,
|
||||
FieldData* result) {
|
||||
constexpr char kOptionsName[] = "options";
|
||||
constexpr char kNodeOptionsName[] = "node_options";
|
||||
std::string parent_type = options_field_util::ParseTypeUrl(
|
||||
std::string(message_data.message_value().type_url()));
|
||||
FieldPath path;
|
||||
Status status;
|
||||
path = GetExtensionPath(parent_type, extension_type, kOptionsName, false);
|
||||
status = GetField(path, message_data, result);
|
||||
if (status.ok()) {
|
||||
return status;
|
||||
}
|
||||
path = GetExtensionPath(parent_type, extension_type, kNodeOptionsName, true);
|
||||
status = GetField(path, message_data, result);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Returns the requested options protobuf for a graph.
|
||||
absl::Status GetGraphOptions(const FieldData& message_data,
|
||||
const std::string& extension_type,
|
||||
FieldData* result) {
|
||||
constexpr char kOptionsName[] = "options";
|
||||
constexpr char kGraphOptionsName[] = "graph_options";
|
||||
std::string parent_type = options_field_util::ParseTypeUrl(
|
||||
std::string(message_data.message_value().type_url()));
|
||||
FieldPath path;
|
||||
Status status;
|
||||
path = GetExtensionPath(parent_type, extension_type, kOptionsName, false);
|
||||
status = GetField(path, message_data, result);
|
||||
if (status.ok()) {
|
||||
return status;
|
||||
}
|
||||
path = GetExtensionPath(parent_type, extension_type, kGraphOptionsName, true);
|
||||
status = GetField(path, message_data, result);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Reads a FieldData value from a protobuf field.
|
||||
absl::Status GetField(const FieldPath& field_path,
|
||||
const FieldData& message_data, FieldData* result) {
|
||||
if (field_path.empty()) {
|
||||
*result->mutable_message_value() = message_data.message_value();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
FieldPathEntry head = field_path.front();
|
||||
FieldPath tail = field_path;
|
||||
tail.erase(tail.begin());
|
||||
if (!head.extension_type.empty()) {
|
||||
MP_RETURN_IF_ERROR(FindExtension(message_data, &head));
|
||||
}
|
||||
if (tail.empty() && FieldCount(message_data, head.field) == 0) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
MP_RETURN_IF_ERROR(GetFieldValue(message_data, head, result));
|
||||
if (IsProtobufAny(head.field)) {
|
||||
*result = ParseProtobufAny(*result);
|
||||
}
|
||||
if (!tail.empty()) {
|
||||
FieldData child = *result;
|
||||
MP_RETURN_IF_ERROR(GetField(tail, child, result));
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Writes a FieldData value into protobuf field.
|
||||
absl::Status SetField(const FieldPath& field_path, const FieldData& value,
|
||||
FieldData* message_data) {
|
||||
if (field_path.empty()) {
|
||||
*message_data->mutable_message_value() = value.message_value();
|
||||
return mediapipe::OkStatus();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
ProtoUtilLite proto_util;
|
||||
const FieldDescriptor* field = field_path.back().first;
|
||||
FieldType field_type = AsFieldType(field->type());
|
||||
std::string field_value;
|
||||
MP_RETURN_IF_ERROR(WriteField(value, field, &field_value));
|
||||
ProtoUtilLite::ProtoPath proto_path = AsProtoPath(field_path);
|
||||
std::string* message_bytes =
|
||||
message_data->mutable_message_value()->mutable_value();
|
||||
int field_count;
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldCount(*message_bytes, proto_path,
|
||||
field_type, &field_count));
|
||||
MP_RETURN_IF_ERROR(
|
||||
proto_util.ReplaceFieldRange(message_bytes, AsProtoPath(field_path),
|
||||
field_count, field_type, {field_value}));
|
||||
return mediapipe::OkStatus();
|
||||
FieldPathEntry head = field_path.front();
|
||||
FieldPath tail = field_path;
|
||||
tail.erase(tail.begin());
|
||||
if (!head.extension_type.empty()) {
|
||||
MP_RETURN_IF_ERROR(FindExtension(*message_data, &head));
|
||||
}
|
||||
if (tail.empty()) {
|
||||
MP_RETURN_IF_ERROR(SetFieldValue(head, value, message_data));
|
||||
} else {
|
||||
FieldData child;
|
||||
MP_RETURN_IF_ERROR(GetFieldValue(*message_data, head, &child));
|
||||
MP_RETURN_IF_ERROR(SetField(tail, value, &child));
|
||||
if (IsProtobufAny(head.field)) {
|
||||
child = SerializeProtobufAny(child);
|
||||
}
|
||||
MP_RETURN_IF_ERROR(SetFieldValue(head, child, message_data));
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Merges a packet value into nested protobuf Message.
|
||||
@@ -308,7 +538,7 @@ absl::Status MergeField(const FieldPath& field_path, const FieldData& value,
|
||||
absl::Status status;
|
||||
FieldType field_type = field_path.empty()
|
||||
? FieldType::TYPE_MESSAGE
|
||||
: AsFieldType(field_path.back().first->type());
|
||||
: AsFieldType(field_path.back().field->type());
|
||||
std::string message_type =
|
||||
(value.has_message_value())
|
||||
? ParseTypeUrl(std::string(value.message_value().type_url()))
|
||||
@@ -317,49 +547,12 @@ absl::Status MergeField(const FieldPath& field_path, const FieldData& value,
|
||||
if (field_type == FieldType::TYPE_MESSAGE) {
|
||||
FieldData b;
|
||||
status.Update(GetField(field_path, *message_data, &b));
|
||||
status.Update(MergeOptionsMessages(b, v, &v));
|
||||
status.Update(MergeMessages(b, v, &v));
|
||||
}
|
||||
status.Update(SetField(field_path, v, message_data));
|
||||
return status;
|
||||
}
|
||||
|
||||
// Reads a packet value from a protobuf field.
|
||||
absl::Status GetField(const FieldPath& field_path,
|
||||
const FieldData& message_data, FieldData* result) {
|
||||
if (field_path.empty()) {
|
||||
*result->mutable_message_value() = message_data.message_value();
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
ProtoUtilLite proto_util;
|
||||
const FieldDescriptor* field = field_path.back().first;
|
||||
FieldType field_type = AsFieldType(field->type());
|
||||
std::vector<std::string> field_values;
|
||||
ProtoUtilLite::ProtoPath proto_path = AsProtoPath(field_path);
|
||||
const std::string& message_bytes = message_data.message_value().value();
|
||||
int field_count;
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldCount(message_bytes, proto_path,
|
||||
field_type, &field_count));
|
||||
if (field_count == 0) {
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
MP_RETURN_IF_ERROR(proto_util.GetFieldRange(message_bytes, proto_path, 1,
|
||||
field_type, &field_values));
|
||||
MP_RETURN_IF_ERROR(ReadField(field_values.front(), field, result));
|
||||
return mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
// Returns the options protobuf for a graph.
|
||||
absl::Status GetOptionsMessage(const CalculatorGraphConfig& config,
|
||||
FieldData* result) {
|
||||
return GetOptionsMessage(config.graph_options(), config.options(), result);
|
||||
}
|
||||
|
||||
// Returns the options protobuf for a node.
|
||||
absl::Status GetOptionsMessage(const CalculatorGraphConfig::Node& node,
|
||||
FieldData* result) {
|
||||
return GetOptionsMessage(node.node_options(), node.options(), result);
|
||||
}
|
||||
|
||||
// Sets the node_options field in a Node, and clears the options field.
|
||||
void SetOptionsMessage(const FieldData& node_options,
|
||||
CalculatorGraphConfig::Node* node) {
|
||||
@@ -367,6 +560,16 @@ void SetOptionsMessage(const FieldData& node_options,
|
||||
node->clear_options();
|
||||
}
|
||||
|
||||
// Serialize a MessageLite to a FieldData.
|
||||
FieldData AsFieldData(const proto_ns::MessageLite& message) {
|
||||
FieldData result;
|
||||
*result.mutable_message_value()->mutable_value() =
|
||||
message.SerializePartialAsString();
|
||||
*result.mutable_message_value()->mutable_type_url() =
|
||||
TypeUrl(message.GetTypeName());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Represents a protobuf enum value stored in a Packet.
|
||||
struct ProtoEnum {
|
||||
ProtoEnum(int32 v) : value(v) {}
|
||||
@@ -415,7 +618,7 @@ absl::Status AsPacket(const FieldData& data, Packet* result) {
|
||||
case FieldData::VALUE_NOT_SET:
|
||||
*result = Packet();
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status AsFieldData(Packet packet, FieldData* result) {
|
||||
@@ -436,7 +639,7 @@ absl::Status AsFieldData(Packet packet, FieldData* result) {
|
||||
packet.GetProtoMessageLite().SerializeAsString());
|
||||
result->mutable_message_value()->set_type_url(
|
||||
TypeUrl(packet.GetProtoMessageLite().GetTypeName()));
|
||||
return mediapipe::OkStatus();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
if (kTypeIds->count(packet.GetTypeId()) == 0) {
|
||||
@@ -473,7 +676,7 @@ absl::Status AsFieldData(Packet packet, FieldData* result) {
|
||||
result->set_string_value(packet.Get<std::string>());
|
||||
break;
|
||||
}
|
||||
return mediapipe::OkStatus();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
std::string TypeUrl(absl::string_view type_name) {
|
||||
|
||||
@@ -19,8 +19,15 @@ namespace tool {
|
||||
// Utility to read and write Packet data from protobuf fields.
|
||||
namespace options_field_util {
|
||||
|
||||
// A chain of nested fields and indexes.
|
||||
using FieldPath = std::vector<std::pair<const FieldDescriptor*, int>>;
|
||||
// A protobuf field and index description.
|
||||
struct FieldPathEntry {
|
||||
const FieldDescriptor* field = nullptr;
|
||||
int index = -1;
|
||||
std::string extension_type;
|
||||
};
|
||||
|
||||
// A chain of nested protobuf fields and indexes.
|
||||
using FieldPath = std::vector<FieldPathEntry>;
|
||||
|
||||
// Writes a field value into protobuf field.
|
||||
absl::Status SetField(const FieldPath& field_path, const FieldData& value,
|
||||
@@ -39,21 +46,26 @@ absl::Status ReadMessage(const std::string& value, const std::string& type_name,
|
||||
Packet* result);
|
||||
|
||||
// Merge two options protobuf field values.
|
||||
absl::Status MergeOptionsMessages(const FieldData& base, const FieldData& over,
|
||||
FieldData* result);
|
||||
absl::Status MergeMessages(const FieldData& base, const FieldData& over,
|
||||
FieldData* result);
|
||||
|
||||
// Returns the options protobuf for a graph.
|
||||
absl::Status GetOptionsMessage(const CalculatorGraphConfig& config,
|
||||
FieldData* result);
|
||||
// Returns the requested options protobuf for a graph.
|
||||
absl::Status GetNodeOptions(const FieldData& message_data,
|
||||
const std::string& extension_type,
|
||||
FieldData* result);
|
||||
|
||||
// Returns the options protobuf for a node.
|
||||
absl::Status GetOptionsMessage(const CalculatorGraphConfig::Node& node,
|
||||
FieldData* result);
|
||||
// Returns the requested options protobuf for a graph node.
|
||||
absl::Status GetGraphOptions(const FieldData& message_data,
|
||||
const std::string& extension_type,
|
||||
FieldData* result);
|
||||
|
||||
// Sets the node_options field in a Node, and clears the options field.
|
||||
void SetOptionsMessage(const FieldData& node_options,
|
||||
CalculatorGraphConfig::Node* node);
|
||||
|
||||
// Serialize a MessageLite to a FieldData.
|
||||
FieldData AsFieldData(const proto_ns::MessageLite& message);
|
||||
|
||||
// Constructs a Packet for a FieldData proto.
|
||||
absl::Status AsPacket(const FieldData& data, Packet* result);
|
||||
|
||||
|
||||
@@ -5,17 +5,42 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "mediapipe/framework/packet.h"
|
||||
#include "mediapipe/framework/packet_type.h"
|
||||
#include "mediapipe/framework/port/advanced_proto_inc.h"
|
||||
#include "mediapipe/framework/port/any_proto.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/framework/tool/name_util.h"
|
||||
#include "mediapipe/framework/tool/options_registry.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
namespace {
|
||||
|
||||
// StrSplit Delimiter to split strings at single colon tokens, ignoring
|
||||
// double-colon tokens.
|
||||
class SingleColonDelimiter {
|
||||
public:
|
||||
SingleColonDelimiter() {}
|
||||
absl::string_view Find(absl::string_view text, size_t pos) const {
|
||||
while (pos < text.length()) {
|
||||
size_t p = text.find(':', pos);
|
||||
p = (p == absl::string_view::npos) ? text.length() : p;
|
||||
if (p >= text.length() - 1 || text[p + 1] != ':') {
|
||||
return text.substr(p, 1);
|
||||
}
|
||||
pos = p + 2;
|
||||
}
|
||||
return text.substr(text.length(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Helper functions for parsing the graph options syntax.
|
||||
class OptionsSyntaxUtil::OptionsSyntaxHelper {
|
||||
public:
|
||||
@@ -31,13 +56,32 @@ class OptionsSyntaxUtil::OptionsSyntaxHelper {
|
||||
// Returns the option protobuf field name for a tag or packet name.
|
||||
absl::string_view OptionFieldName(absl::string_view name) { return name; }
|
||||
|
||||
// Return the extension-type specified for an option field.
|
||||
absl::string_view ExtensionType(absl::string_view option_name) {
|
||||
constexpr absl::string_view kExt = "Ext::";
|
||||
if (absl::StartsWithIgnoreCase(option_name, kExt)) {
|
||||
return option_name.substr(kExt.size());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// Returns the field names encoded in an options tag.
|
||||
std::vector<absl::string_view> OptionTagNames(absl::string_view tag) {
|
||||
if (absl::StartsWith(tag, syntax_.tag_name)) {
|
||||
tag = tag.substr(syntax_.tag_name.length());
|
||||
} else if (absl::StartsWith(tag, syntax_.packet_name)) {
|
||||
tag = tag.substr(syntax_.packet_name.length());
|
||||
}
|
||||
if (absl::StartsWith(tag, syntax_.separator)) {
|
||||
tag = tag.substr(syntax_.separator.length());
|
||||
}
|
||||
return absl::StrSplit(tag, syntax_.separator);
|
||||
}
|
||||
|
||||
// Returns the field-path for an option stream-tag.
|
||||
FieldPath OptionFieldPath(const std::string& tag,
|
||||
FieldPath OptionFieldPath(absl::string_view tag,
|
||||
const Descriptor* descriptor) {
|
||||
int prefix = syntax_.tag_name.length() + syntax_.separator.length();
|
||||
std::string suffix = tag.substr(prefix);
|
||||
std::vector<absl::string_view> name_tags =
|
||||
absl::StrSplit(suffix, syntax_.separator);
|
||||
std::vector<absl::string_view> name_tags = OptionTagNames(tag);
|
||||
FieldPath result;
|
||||
for (absl::string_view name_tag : name_tags) {
|
||||
if (name_tag.empty()) {
|
||||
@@ -46,8 +90,16 @@ class OptionsSyntaxUtil::OptionsSyntaxHelper {
|
||||
absl::string_view option_name = OptionFieldName(name_tag);
|
||||
int index;
|
||||
if (absl::SimpleAtoi(option_name, &index)) {
|
||||
result.back().second = index;
|
||||
result.back().index = index;
|
||||
}
|
||||
if (!ExtensionType(option_name).empty()) {
|
||||
std::string extension_type = std::string(ExtensionType(option_name));
|
||||
result.push_back({nullptr, 0, extension_type});
|
||||
descriptor = OptionsRegistry::GetProtobufDescriptor(extension_type);
|
||||
} else {
|
||||
if (descriptor == nullptr) {
|
||||
break;
|
||||
}
|
||||
auto field = descriptor->FindFieldByName(std::string(option_name));
|
||||
descriptor = field ? field->message_type() : nullptr;
|
||||
result.push_back({std::move(field), 0});
|
||||
@@ -78,7 +130,7 @@ class OptionsSyntaxUtil::OptionsSyntaxHelper {
|
||||
}
|
||||
|
||||
// Converts slash-separated field names into a tag name.
|
||||
std::string OptionFieldsTag(const std::string& option_names) {
|
||||
std::string OptionFieldsTag(absl::string_view option_names) {
|
||||
std::string tag_prefix = syntax_.tag_name + syntax_.separator;
|
||||
std::vector<absl::string_view> names = absl::StrSplit(option_names, '/');
|
||||
if (!names.empty() && names[0] == syntax_.tag_name) {
|
||||
@@ -129,15 +181,18 @@ OptionsSyntaxUtil::OptionsSyntaxUtil(const std::string& tag_name,
|
||||
|
||||
OptionsSyntaxUtil::~OptionsSyntaxUtil() {}
|
||||
|
||||
std::string OptionsSyntaxUtil::OptionFieldsTag(
|
||||
const std::string& option_names) {
|
||||
std::string OptionsSyntaxUtil::OptionFieldsTag(absl::string_view option_names) {
|
||||
return syntax_helper_->OptionFieldsTag(option_names);
|
||||
}
|
||||
|
||||
OptionsSyntaxUtil::FieldPath OptionsSyntaxUtil::OptionFieldPath(
|
||||
const std::string& tag, const Descriptor* descriptor) {
|
||||
absl::string_view tag, const Descriptor* descriptor) {
|
||||
return syntax_helper_->OptionFieldPath(tag, descriptor);
|
||||
}
|
||||
std::vector<absl::string_view> OptionsSyntaxUtil::StrSplitTags(
|
||||
absl::string_view tag_and_name) {
|
||||
return absl::StrSplit(tag_and_name, SingleColonDelimiter());
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -28,12 +28,15 @@ class OptionsSyntaxUtil {
|
||||
~OptionsSyntaxUtil();
|
||||
|
||||
// Converts slash-separated field names into a tag name.
|
||||
std::string OptionFieldsTag(const std::string& option_names);
|
||||
std::string OptionFieldsTag(absl::string_view option_names);
|
||||
|
||||
// Returns the field-path for an option stream-tag.
|
||||
FieldPath OptionFieldPath(const std::string& tag,
|
||||
FieldPath OptionFieldPath(absl::string_view tag,
|
||||
const Descriptor* descriptor);
|
||||
|
||||
// Splits a std::string into "tag" and "name" delimited by a single colon.
|
||||
std::vector<absl::string_view> StrSplitTags(absl::string_view tag_and_name);
|
||||
|
||||
private:
|
||||
class OptionsSyntaxHelper;
|
||||
std::unique_ptr<OptionsSyntaxHelper> syntax_helper_;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "mediapipe/framework/calculator_context.h"
|
||||
#include "mediapipe/framework/input_stream_shard.h"
|
||||
#include "mediapipe/framework/output_side_packet.h"
|
||||
@@ -24,50 +25,77 @@
|
||||
namespace mediapipe {
|
||||
namespace tool {
|
||||
|
||||
using options_field_util::FieldPath;
|
||||
using options_field_util::GetField;
|
||||
using options_field_util::GetGraphOptions;
|
||||
using options_field_util::GetNodeOptions;
|
||||
using options_field_util::MergeField;
|
||||
using options_field_util::MergeMessages;
|
||||
|
||||
// Returns the type for the root options message if specified.
|
||||
std::string ExtensionType(const std::string& option_fields_tag) {
|
||||
OptionsSyntaxUtil syntax_util;
|
||||
options_field_util::FieldPath field_path =
|
||||
syntax_util.OptionFieldPath(option_fields_tag, nullptr);
|
||||
std::string result = !field_path.empty() ? field_path[0].extension_type : "";
|
||||
return !result.empty() ? result : "*";
|
||||
}
|
||||
|
||||
// Constructs a FieldPath for field names starting at a message type.
|
||||
FieldPath GetPath(const std::string& path_tag,
|
||||
const std::string& message_type) {
|
||||
OptionsSyntaxUtil syntax_util;
|
||||
const Descriptor* descriptor =
|
||||
OptionsRegistry::GetProtobufDescriptor(message_type);
|
||||
return syntax_util.OptionFieldPath(path_tag, descriptor);
|
||||
}
|
||||
|
||||
// Returns the message type for a FieldData.
|
||||
std::string MessageType(FieldData message) {
|
||||
return options_field_util::ParseTypeUrl(
|
||||
std::string(message.message_value().type_url()));
|
||||
}
|
||||
|
||||
// Copy literal options from graph_options to node_options.
|
||||
absl::Status CopyLiteralOptions(CalculatorGraphConfig::Node parent_node,
|
||||
CalculatorGraphConfig* config) {
|
||||
Status status;
|
||||
FieldData config_options, parent_node_options, graph_options;
|
||||
status.Update(
|
||||
options_field_util::GetOptionsMessage(*config, &config_options));
|
||||
status.Update(
|
||||
options_field_util::GetOptionsMessage(parent_node, &parent_node_options));
|
||||
status.Update(options_field_util::MergeOptionsMessages(
|
||||
config_options, parent_node_options, &graph_options));
|
||||
const Descriptor* options_descriptor =
|
||||
OptionsRegistry::GetProtobufDescriptor(options_field_util::ParseTypeUrl(
|
||||
std::string(graph_options.message_value().type_url())));
|
||||
if (!options_descriptor) {
|
||||
return status;
|
||||
}
|
||||
FieldData graph_data = options_field_util::AsFieldData(*config);
|
||||
FieldData parent_data = options_field_util::AsFieldData(parent_node);
|
||||
|
||||
OptionsSyntaxUtil syntax_util;
|
||||
for (auto& node : *config->mutable_node()) {
|
||||
FieldData node_data;
|
||||
status.Update(options_field_util::GetOptionsMessage(node, &node_data));
|
||||
if (!node_data.has_message_value() || node.option_value_size() == 0) {
|
||||
continue;
|
||||
}
|
||||
const Descriptor* node_options_descriptor =
|
||||
OptionsRegistry::GetProtobufDescriptor(options_field_util::ParseTypeUrl(
|
||||
std::string(node_data.message_value().type_url())));
|
||||
if (!node_options_descriptor) {
|
||||
continue;
|
||||
}
|
||||
FieldData node_data = options_field_util::AsFieldData(node);
|
||||
|
||||
for (const std::string& option_def : node.option_value()) {
|
||||
std::vector<std::string> tag_and_name = absl::StrSplit(option_def, ':');
|
||||
std::vector<absl::string_view> tag_and_name =
|
||||
syntax_util.StrSplitTags(option_def);
|
||||
std::string graph_tag = syntax_util.OptionFieldsTag(tag_and_name[1]);
|
||||
std::string graph_extension_type = ExtensionType(graph_tag);
|
||||
std::string node_tag = syntax_util.OptionFieldsTag(tag_and_name[0]);
|
||||
std::string node_extension_type = ExtensionType(node_tag);
|
||||
FieldData graph_options;
|
||||
GetGraphOptions(graph_data, graph_extension_type, &graph_options)
|
||||
.IgnoreError();
|
||||
FieldData parent_options;
|
||||
GetNodeOptions(parent_data, graph_extension_type, &parent_options)
|
||||
.IgnoreError();
|
||||
status.Update(
|
||||
MergeMessages(graph_options, parent_options, &graph_options));
|
||||
FieldData node_options;
|
||||
status.Update(
|
||||
GetNodeOptions(node_data, node_extension_type, &node_options));
|
||||
if (!node_options.has_message_value() ||
|
||||
!graph_options.has_message_value()) {
|
||||
continue;
|
||||
}
|
||||
FieldPath graph_path = GetPath(graph_tag, MessageType(graph_options));
|
||||
FieldPath node_path = GetPath(node_tag, MessageType(node_options));
|
||||
FieldData packet_data;
|
||||
status.Update(options_field_util::GetField(
|
||||
syntax_util.OptionFieldPath(graph_tag, options_descriptor),
|
||||
graph_options, &packet_data));
|
||||
status.Update(options_field_util::MergeField(
|
||||
syntax_util.OptionFieldPath(node_tag, node_options_descriptor),
|
||||
packet_data, &node_data));
|
||||
status.Update(GetField(graph_path, graph_options, &packet_data));
|
||||
status.Update(MergeField(node_path, packet_data, &node_options));
|
||||
options_field_util::SetOptionsMessage(node_options, &node);
|
||||
}
|
||||
options_field_util::SetOptionsMessage(node_data, &node);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/deps/message_matchers.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/framework/testdata/night_light_calculator.pb.h"
|
||||
#include "mediapipe/framework/tool/node_chain_subgraph.pb.h"
|
||||
#include "mediapipe/framework/tool/options_field_util.h"
|
||||
#include "mediapipe/framework/tool/options_registry.h"
|
||||
#include "mediapipe/framework/tool/options_syntax_util.h"
|
||||
|
||||
@@ -51,6 +53,35 @@ class NightLightCalculator : public CalculatorBase {
|
||||
};
|
||||
REGISTER_CALCULATOR(NightLightCalculator);
|
||||
|
||||
using tool::options_field_util::FieldPath;
|
||||
|
||||
// Validates FieldPathEntry contents.
|
||||
bool Equals(const tool::options_field_util::FieldPathEntry& entry,
|
||||
const std::string& field_name, int index,
|
||||
const std::string& extension_type) {
|
||||
const std::string& name = entry.field ? entry.field->name() : "";
|
||||
return name == field_name && entry.index == index &&
|
||||
entry.extension_type == extension_type;
|
||||
}
|
||||
|
||||
// Serializes a MessageLite into FieldData.message_value.
|
||||
FieldData AsFieldData(const proto_ns::MessageLite& message) {
|
||||
FieldData result;
|
||||
*result.mutable_message_value()->mutable_value() =
|
||||
message.SerializeAsString();
|
||||
result.mutable_message_value()->set_type_url(message.GetTypeName());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the type for the root options message if specified.
|
||||
std::string ExtensionType(const std::string& option_fields_tag) {
|
||||
tool::OptionsSyntaxUtil syntax_util;
|
||||
tool::options_field_util::FieldPath field_path =
|
||||
syntax_util.OptionFieldPath(option_fields_tag, nullptr);
|
||||
std::string result = !field_path.empty() ? field_path[0].extension_type : "";
|
||||
return !result.empty() ? result : "*";
|
||||
}
|
||||
|
||||
// Tests for calculator and graph options.
|
||||
//
|
||||
class OptionsUtilTest : public ::testing::Test {
|
||||
@@ -150,8 +181,8 @@ TEST_F(OptionsUtilTest, OptionsSyntaxUtil) {
|
||||
EXPECT_EQ(tag, "OPTIONS/sub_options/num_lights");
|
||||
field_path = syntax_util.OptionFieldPath(tag, descriptor);
|
||||
EXPECT_EQ(field_path.size(), 2);
|
||||
EXPECT_EQ(field_path[0].first->name(), "sub_options");
|
||||
EXPECT_EQ(field_path[1].first->name(), "num_lights");
|
||||
EXPECT_EQ(field_path[0].field->name(), "sub_options");
|
||||
EXPECT_EQ(field_path[1].field->name(), "num_lights");
|
||||
}
|
||||
{
|
||||
// A tag syntax with a text-coded separator.
|
||||
@@ -160,10 +191,100 @@ TEST_F(OptionsUtilTest, OptionsSyntaxUtil) {
|
||||
EXPECT_EQ(tag, "OPTIONS_Z0Z_sub_options_Z0Z_num_lights");
|
||||
field_path = syntax_util.OptionFieldPath(tag, descriptor);
|
||||
EXPECT_EQ(field_path.size(), 2);
|
||||
EXPECT_EQ(field_path[0].first->name(), "sub_options");
|
||||
EXPECT_EQ(field_path[1].first->name(), "num_lights");
|
||||
EXPECT_EQ(field_path[0].field->name(), "sub_options");
|
||||
EXPECT_EQ(field_path[1].field->name(), "num_lights");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(OptionsUtilTest, OptionFieldPath) {
|
||||
tool::OptionsSyntaxUtil syntax_util;
|
||||
std::vector<absl::string_view> split;
|
||||
split = syntax_util.StrSplitTags("a/graph/option:a/node/option");
|
||||
EXPECT_EQ(2, split.size());
|
||||
EXPECT_EQ(split[0], "a/graph/option");
|
||||
EXPECT_EQ(split[1], "a/node/option");
|
||||
split = syntax_util.StrSplitTags("Ext::a/graph/option:Ext::a/node/option");
|
||||
EXPECT_EQ(2, split.size());
|
||||
EXPECT_EQ(split[0], "Ext::a/graph/option");
|
||||
EXPECT_EQ(split[1], "Ext::a/node/option");
|
||||
|
||||
split =
|
||||
syntax_util.StrSplitTags("chain_length:options/sub_options/num_lights");
|
||||
EXPECT_EQ(2, split.size());
|
||||
EXPECT_EQ(split[0], "chain_length");
|
||||
EXPECT_EQ(split[1], "options/sub_options/num_lights");
|
||||
const tool::Descriptor* descriptor =
|
||||
tool::OptionsRegistry::GetProtobufDescriptor(
|
||||
"mediapipe.NightLightCalculatorOptions");
|
||||
tool::options_field_util::FieldPath field_path =
|
||||
syntax_util.OptionFieldPath(split[1], descriptor);
|
||||
EXPECT_EQ(field_path.size(), 2);
|
||||
EXPECT_EQ(field_path[0].field->name(), "sub_options");
|
||||
EXPECT_EQ(field_path[1].field->name(), "num_lights");
|
||||
}
|
||||
|
||||
TEST_F(OptionsUtilTest, FindOptionsMessage) {
|
||||
tool::OptionsSyntaxUtil syntax_util;
|
||||
std::vector<absl::string_view> split;
|
||||
split =
|
||||
syntax_util.StrSplitTags("chain_length:options/sub_options/num_lights");
|
||||
EXPECT_EQ(2, split.size());
|
||||
EXPECT_EQ(split[0], "chain_length");
|
||||
EXPECT_EQ(split[1], "options/sub_options/num_lights");
|
||||
const tool::Descriptor* descriptor =
|
||||
tool::OptionsRegistry::GetProtobufDescriptor(
|
||||
"mediapipe.NightLightCalculatorOptions");
|
||||
tool::options_field_util::FieldPath field_path =
|
||||
syntax_util.OptionFieldPath(split[1], descriptor);
|
||||
EXPECT_EQ(field_path.size(), 2);
|
||||
EXPECT_TRUE(Equals(field_path[0], "sub_options", 0, ""));
|
||||
EXPECT_TRUE(Equals(field_path[1], "num_lights", 0, ""));
|
||||
|
||||
{
|
||||
// NightLightCalculatorOptions in Node.options.
|
||||
CalculatorGraphConfig::Node node;
|
||||
NightLightCalculatorOptions* options =
|
||||
node.mutable_options()->MutableExtension(
|
||||
NightLightCalculatorOptions::ext);
|
||||
options->mutable_sub_options()->add_num_lights(33);
|
||||
|
||||
// Retrieve the specified option.
|
||||
FieldData node_data = AsFieldData(node);
|
||||
auto path = field_path;
|
||||
std::string node_extension_type = ExtensionType(std::string(split[1]));
|
||||
FieldData node_options;
|
||||
MP_EXPECT_OK(tool::options_field_util::GetNodeOptions(
|
||||
node_data, node_extension_type, &node_options));
|
||||
FieldData packet_data;
|
||||
MP_EXPECT_OK(tool::options_field_util::GetField(field_path, node_options,
|
||||
&packet_data));
|
||||
EXPECT_EQ(packet_data.value_case(), FieldData::kInt32Value);
|
||||
EXPECT_EQ(packet_data.int32_value(), 33);
|
||||
}
|
||||
|
||||
{
|
||||
// NightLightCalculatorOptions in Node.node_options.
|
||||
CalculatorGraphConfig::Node node;
|
||||
NightLightCalculatorOptions options;
|
||||
options.mutable_sub_options()->add_num_lights(33);
|
||||
node.add_node_options()->PackFrom(options);
|
||||
|
||||
// Retrieve the specified option.
|
||||
FieldData node_data = AsFieldData(node);
|
||||
auto path = field_path;
|
||||
std::string node_extension_type = ExtensionType(std::string(split[1]));
|
||||
FieldData node_options;
|
||||
MP_EXPECT_OK(tool::options_field_util::GetNodeOptions(
|
||||
node_data, node_extension_type, &node_options));
|
||||
FieldData packet_data;
|
||||
MP_EXPECT_OK(tool::options_field_util::GetField(field_path, node_options,
|
||||
&packet_data));
|
||||
EXPECT_EQ(packet_data.value_case(), FieldData::kInt32Value);
|
||||
EXPECT_EQ(packet_data.int32_value(), 33);
|
||||
}
|
||||
|
||||
// TODO: Test with specified extension_type.
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
|
||||
Reference in New Issue
Block a user