Project import generated by Copybara.
GitOrigin-RevId: b137378673f7d66d41bcd46e4fc3a0d9ef254894
This commit is contained in:
@@ -688,6 +688,12 @@ cc_library(
|
||||
cc_library(
|
||||
name = "demangle",
|
||||
hdrs = ["demangle.h"],
|
||||
defines = select({
|
||||
"//mediapipe/framework/profiler:android_release": [
|
||||
"MEDIAPIPE_HAS_CXA_DEMANGLE=0",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
@@ -1713,3 +1719,10 @@ cc_test(
|
||||
"//mediapipe/framework/tool/testdata:dub_quad_test_subgraph",
|
||||
],
|
||||
)
|
||||
|
||||
# Expose the proto source files for building mediapipe AAR.
|
||||
filegroup(
|
||||
name = "protos_src",
|
||||
srcs = glob(["*.proto"]),
|
||||
visibility = ["//mediapipe:__subpackages__"],
|
||||
)
|
||||
|
||||
@@ -756,7 +756,7 @@ TEST(CalculatorGraphBoundsTest, BoundWithoutInputPackets) {
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
// Shows that when fixed-size-input-stream-hanlder drops packets,
|
||||
// Shows that when fixed-size-input-stream-handler drops packets,
|
||||
// no timetamp bounds are announced.
|
||||
TEST(CalculatorGraphBoundsTest, FixedSizeHandlerBounds) {
|
||||
// LambdaCalculator with FixedSizeInputStreamHandler will drop packets
|
||||
@@ -876,5 +876,93 @@ TEST(CalculatorGraphBoundsTest, FixedSizeHandlerBounds) {
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
// A Calculator that outputs only the last packet from its input stream.
|
||||
class LastPacketCalculator : public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->Inputs().Index(0).SetAny();
|
||||
cc->Outputs().Index(0).SetAny();
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
::mediapipe::Status Open(CalculatorContext* cc) final {
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
::mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
cc->Outputs().Index(0).SetNextTimestampBound(cc->InputTimestamp());
|
||||
last_packet_ = cc->Inputs().Index(0).Value();
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
::mediapipe::Status Close(CalculatorContext* cc) final {
|
||||
cc->Outputs().Index(0).AddPacket(last_packet_);
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
private:
|
||||
Packet last_packet_;
|
||||
};
|
||||
REGISTER_CALCULATOR(LastPacketCalculator);
|
||||
|
||||
// Shows that the last packet in an input stream can be detected.
|
||||
TEST(CalculatorGraphBoundsTest, LastPacketCheck) {
|
||||
// LastPacketCalculator emits only the last input stream packet.
|
||||
// It emits a timestamp bound after the arrival of a successor input stream
|
||||
// packet or input stream close. The output "last_output" shows the
|
||||
// last packet, and "output" shows the timestamp bounds.
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
input_stream: 'input'
|
||||
output_stream: 'output'
|
||||
output_stream: 'last_output'
|
||||
node {
|
||||
calculator: 'PassThroughCalculator'
|
||||
input_stream: 'input'
|
||||
output_stream: 'input_2'
|
||||
}
|
||||
node {
|
||||
calculator: 'LastPacketCalculator'
|
||||
input_stream: 'input_2'
|
||||
output_stream: 'last_packet'
|
||||
}
|
||||
node {
|
||||
calculator: 'PassThroughCalculator'
|
||||
input_stream: 'input'
|
||||
input_stream: 'last_packet'
|
||||
output_stream: 'output'
|
||||
output_stream: 'last_output'
|
||||
}
|
||||
)");
|
||||
CalculatorGraph graph;
|
||||
std::vector<Packet> output_packets;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.ObserveOutputStream("output", [&](const Packet& p) {
|
||||
output_packets.push_back(p);
|
||||
return ::mediapipe::OkStatus();
|
||||
}));
|
||||
std::vector<Packet> last_output_packets;
|
||||
MP_ASSERT_OK(graph.ObserveOutputStream("last_output", [&](const Packet& p) {
|
||||
last_output_packets.push_back(p);
|
||||
return ::mediapipe::OkStatus();
|
||||
}));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
// Add four packets into the graph.
|
||||
constexpr int kNumInputs = 4;
|
||||
for (int i = 0; i < kNumInputs; ++i) {
|
||||
Packet p = MakePacket<int>(33).At(Timestamp(i));
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("input", p));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
EXPECT_EQ(i, output_packets.size());
|
||||
EXPECT_EQ(0, last_output_packets.size());
|
||||
}
|
||||
|
||||
// Shutdown the graph.
|
||||
MP_ASSERT_OK(graph.CloseAllPacketSources());
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
EXPECT_EQ(kNumInputs, output_packets.size());
|
||||
EXPECT_EQ(1, last_output_packets.size());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -743,5 +743,66 @@ TEST(CalculatorGraph, GetOutputSidePacket) {
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::string HugeModel;
|
||||
|
||||
// Generates an output-side-packet once for each calculator-graph.
|
||||
class OutputSidePacketCachedCalculator : public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->OutputSidePackets().Index(0).Set<HugeModel>();
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) final {
|
||||
cc->OutputSidePackets().Index(0).Set(MakePacket<HugeModel>(
|
||||
R"(An expensive side-packet created only once per graph)"));
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) final {
|
||||
LOG(FATAL) << "Not reached.";
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
};
|
||||
REGISTER_CALCULATOR(OutputSidePacketCachedCalculator);
|
||||
|
||||
// Returns true if two packets hold the same data.
|
||||
bool Equals(Packet p1, Packet p2) {
|
||||
return packet_internal::GetHolder(p1) == packet_internal::GetHolder(p2);
|
||||
}
|
||||
|
||||
TEST(CalculatorGraph, OutputSidePacketCached) {
|
||||
CalculatorGraphConfig config =
|
||||
::mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(R"(
|
||||
node {
|
||||
calculator: "OutputSidePacketCachedCalculator"
|
||||
output_side_packet: "model"
|
||||
}
|
||||
node {
|
||||
calculator: "SidePacketToStreamPacketCalculator"
|
||||
input_side_packet: "model"
|
||||
output_stream: "output"
|
||||
}
|
||||
)");
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
std::vector<Packet> output_packets;
|
||||
MP_ASSERT_OK(graph.ObserveOutputStream(
|
||||
"output", [&output_packets](const Packet& packet) {
|
||||
output_packets.push_back(packet);
|
||||
return ::mediapipe::OkStatus();
|
||||
}));
|
||||
|
||||
// Run the graph three times.
|
||||
for (int run = 0; run < 3; ++run) {
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
ASSERT_EQ(3, output_packets.size());
|
||||
for (int run = 0; run < output_packets.size(); ++run) {
|
||||
EXPECT_TRUE(Equals(output_packets[0], output_packets[run]));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -391,6 +391,38 @@ void CalculatorNode::SetMaxInputStreamQueueSize(int max_queue_size) {
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Returns the Packet sent to an OutputSidePacket, or an empty packet
|
||||
// if none available.
|
||||
const Packet GetPacket(const OutputSidePacket& out) {
|
||||
auto impl = dynamic_cast<const OutputSidePacketImpl*>(&out);
|
||||
return (impl == nullptr) ? Packet() : impl->GetPacket();
|
||||
}
|
||||
|
||||
// Resends the output-side-packets from the previous graph run.
|
||||
::mediapipe::Status ResendSidePackets(CalculatorContext* cc) {
|
||||
auto& outs = cc->OutputSidePackets();
|
||||
for (CollectionItemId id = outs.BeginId(); id < outs.EndId(); ++id) {
|
||||
Packet packet = GetPacket(outs.Get(id));
|
||||
if (!packet.IsEmpty()) {
|
||||
// OutputSidePacket::Set re-announces the side-packet to its mirrors.
|
||||
outs.Get(id).Set(packet);
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool CalculatorNode::OutputsAreConstant(CalculatorContext* cc) {
|
||||
if (cc->Inputs().NumEntries() > 0 || cc->Outputs().NumEntries() > 0) {
|
||||
return false;
|
||||
}
|
||||
if (input_side_packet_handler_.InputSidePacketsChanged()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
::mediapipe::Status CalculatorNode::OpenNode() {
|
||||
VLOG(2) << "CalculatorNode::OpenNode() for " << DebugName();
|
||||
|
||||
@@ -407,8 +439,9 @@ void CalculatorNode::SetMaxInputStreamQueueSize(int max_queue_size) {
|
||||
default_context, Timestamp::Unstarted());
|
||||
|
||||
::mediapipe::Status result;
|
||||
|
||||
{
|
||||
if (OutputsAreConstant(default_context)) {
|
||||
result = ResendSidePackets(default_context);
|
||||
} else {
|
||||
MEDIAPIPE_PROFILING(OPEN, default_context);
|
||||
LegacyCalculatorSupport::Scoped<CalculatorContext> s(default_context);
|
||||
result = calculator_->Open(default_context);
|
||||
@@ -494,7 +527,10 @@ void CalculatorNode::CloseOutputStreams(OutputStreamShardSet* outputs) {
|
||||
|
||||
::mediapipe::Status result;
|
||||
|
||||
{
|
||||
if (OutputsAreConstant(default_context)) {
|
||||
// Do nothing.
|
||||
result = ::mediapipe::OkStatus();
|
||||
} else {
|
||||
MEDIAPIPE_PROFILING(CLOSE, default_context);
|
||||
LegacyCalculatorSupport::Scoped<CalculatorContext> s(default_context);
|
||||
result = calculator_->Close(default_context);
|
||||
@@ -770,7 +806,10 @@ std::string CalculatorNode::DebugName() const {
|
||||
|
||||
VLOG(2) << "Calling Calculator::Process() for node: " << DebugName();
|
||||
|
||||
{
|
||||
if (OutputsAreConstant(calculator_context)) {
|
||||
// Do nothing.
|
||||
result = ::mediapipe::OkStatus();
|
||||
} else {
|
||||
MEDIAPIPE_PROFILING(PROCESS, calculator_context);
|
||||
LegacyCalculatorSupport::Scoped<CalculatorContext> s(
|
||||
calculator_context);
|
||||
|
||||
@@ -280,6 +280,9 @@ class CalculatorNode {
|
||||
// Get a std::string describing the input streams.
|
||||
std::string DebugInputStreamNames() const;
|
||||
|
||||
// Returns true if all outputs will be identical to the previous graph run.
|
||||
bool OutputsAreConstant(CalculatorContext* cc);
|
||||
|
||||
// The calculator.
|
||||
std::unique_ptr<CalculatorBase> calculator_;
|
||||
// Keeps data which a Calculator subclass needs access to.
|
||||
|
||||
@@ -240,6 +240,22 @@ class Collection {
|
||||
return tag_map_->EndId(tag);
|
||||
}
|
||||
|
||||
// Equal Collections contain equal mappings and equal elements.
|
||||
bool operator==(const Collection<T>& other) const {
|
||||
if (tag_map_->Mapping() != other.TagMap()->Mapping()) {
|
||||
return false;
|
||||
}
|
||||
for (CollectionItemId id = BeginId(); id < EndId(); ++id) {
|
||||
if (Get(id) != other.Get(id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const Collection<T>& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
// An iterator which is identical to ItType** except that the
|
||||
// dereference operator (operator*) does a double dereference and
|
||||
|
||||
@@ -15,23 +15,25 @@
|
||||
#ifndef MEDIAPIPE_FRAMEWORK_DEMANGLE_H_
|
||||
#define MEDIAPIPE_FRAMEWORK_DEMANGLE_H_
|
||||
|
||||
#ifndef MEDIAPIPE_HAS_CXA_DEMANGLE
|
||||
// We only support some compilers that support __cxa_demangle.
|
||||
// TODO: Checks if Android NDK has fixed this issue or not.
|
||||
#if defined(__ANDROID__) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define HAS_CXA_DEMANGLE 0
|
||||
#define MEDIAPIPE_HAS_CXA_DEMANGLE 0
|
||||
#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
|
||||
!defined(__mips__)
|
||||
#define HAS_CXA_DEMANGLE 1
|
||||
#define MEDIAPIPE_HAS_CXA_DEMANGLE 1
|
||||
#elif defined(__clang__) && !defined(_MSC_VER)
|
||||
#define HAS_CXA_DEMANGLE 1
|
||||
#define MEDIAPIPE_HAS_CXA_DEMANGLE 1
|
||||
#else
|
||||
#define HAS_CXA_DEMANGLE 0
|
||||
#define MEDIAPIPE_HAS_CXA_DEMANGLE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#if HAS_CXA_DEMANGLE
|
||||
#if MEDIAPIPE_HAS_CXA_DEMANGLE
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
@@ -65,7 +67,7 @@ namespace mediapipe {
|
||||
inline std::string Demangle(const char* mangled) {
|
||||
int status = 0;
|
||||
char* demangled = nullptr;
|
||||
#if HAS_CXA_DEMANGLE
|
||||
#if MEDIAPIPE_HAS_CXA_DEMANGLE
|
||||
demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);
|
||||
#endif
|
||||
std::string out;
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
# Description:
|
||||
# The dependencies of mediapipe.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
load("//mediapipe/framework/port:build_config.bzl", "mediapipe_cc_proto_library")
|
||||
load("//mediapipe/framework/port:build_config.bzl", "mediapipe_py_proto_library")
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
|
||||
@@ -66,5 +66,9 @@ message ImageFormat {
|
||||
// LAB, interleaved: one byte for L, then one byte for a, then one
|
||||
// byte for b for each pixel.
|
||||
LAB8 = 10;
|
||||
|
||||
// sBGRA, interleaved: one byte for B, one byte for G, one byte for R,
|
||||
// one byte for alpha or unused. This is the N32 format for Skia.
|
||||
SBGRA = 11;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +279,8 @@ int ImageFrame::NumberOfChannelsForFormat(ImageFormat::Format format) {
|
||||
return 1;
|
||||
case ImageFormat::LAB8:
|
||||
return 3;
|
||||
case ImageFormat::SBGRA:
|
||||
return 4;
|
||||
default:
|
||||
LOG(FATAL) << InvalidFormatString(format);
|
||||
}
|
||||
@@ -304,6 +306,8 @@ int ImageFrame::ChannelSizeForFormat(ImageFormat::Format format) {
|
||||
return sizeof(float);
|
||||
case ImageFormat::LAB8:
|
||||
return sizeof(uint8);
|
||||
case ImageFormat::SBGRA:
|
||||
return sizeof(uint8);
|
||||
default:
|
||||
LOG(FATAL) << InvalidFormatString(format);
|
||||
}
|
||||
@@ -329,6 +333,8 @@ int ImageFrame::ByteDepthForFormat(ImageFormat::Format format) {
|
||||
return 4;
|
||||
case ImageFormat::LAB8:
|
||||
return 1;
|
||||
case ImageFormat::SBGRA:
|
||||
return 1;
|
||||
default:
|
||||
LOG(FATAL) << InvalidFormatString(format);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ int GetMatType(const mediapipe::ImageFormat::Format format) {
|
||||
case mediapipe::ImageFormat::LAB8:
|
||||
type = CV_8U;
|
||||
break;
|
||||
case mediapipe::ImageFormat::SBGRA:
|
||||
type = CV_8U;
|
||||
break;
|
||||
default:
|
||||
// Invalid or unknown; Default to uchar.
|
||||
type = CV_8U;
|
||||
|
||||
@@ -32,3 +32,8 @@ message NormalizedLandmark {
|
||||
optional float y = 2;
|
||||
optional float z = 3;
|
||||
}
|
||||
|
||||
// Group of NormalizedLandmark protos.
|
||||
message NormalizedLandmarkList {
|
||||
repeated NormalizedLandmark landmark = 1;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace mediapipe {
|
||||
std::function<void()> input_side_packets_ready_callback,
|
||||
std::function<void(::mediapipe::Status)> error_callback) {
|
||||
int missing_input_side_packet_count;
|
||||
prev_input_side_packets_ = std::move(input_side_packets_);
|
||||
ASSIGN_OR_RETURN(
|
||||
input_side_packets_,
|
||||
tool::FillPacketSet(*input_side_packet_types, all_side_packets,
|
||||
@@ -41,6 +42,12 @@ namespace mediapipe {
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
bool InputSidePacketHandler::InputSidePacketsChanged() {
|
||||
return prev_input_side_packets_ == nullptr ||
|
||||
input_side_packets_ == nullptr ||
|
||||
*input_side_packets_ != *prev_input_side_packets_;
|
||||
}
|
||||
|
||||
void InputSidePacketHandler::Set(CollectionItemId id, const Packet& packet) {
|
||||
::mediapipe::Status status = SetInternal(id, packet);
|
||||
if (!status.ok()) {
|
||||
|
||||
@@ -52,6 +52,10 @@ class InputSidePacketHandler {
|
||||
|
||||
const PacketSet& InputSidePackets() const { return *input_side_packets_; }
|
||||
|
||||
// Returns true if the set of input-side-packets has changed since the
|
||||
// previous run.
|
||||
bool InputSidePacketsChanged();
|
||||
|
||||
// Returns the number of missing input side packets.
|
||||
int MissingInputSidePacketCount() const {
|
||||
return missing_input_side_packet_count_.load(std::memory_order_relaxed);
|
||||
@@ -68,6 +72,7 @@ class InputSidePacketHandler {
|
||||
const PacketTypeSet* input_side_packet_types_;
|
||||
|
||||
std::unique_ptr<PacketSet> input_side_packets_;
|
||||
std::unique_ptr<PacketSet> prev_input_side_packets_;
|
||||
|
||||
std::atomic<int> missing_input_side_packet_count_{0};
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace mediapipe {
|
||||
void OutputSidePacketImpl::PrepareForRun(
|
||||
std::function<void(::mediapipe::Status)> error_callback) {
|
||||
error_callback_ = std::move(error_callback);
|
||||
packet_ = Packet();
|
||||
initialized_ = false;
|
||||
}
|
||||
|
||||
void OutputSidePacketImpl::Set(const Packet& packet) {
|
||||
@@ -47,7 +47,7 @@ void OutputSidePacketImpl::AddMirror(
|
||||
}
|
||||
|
||||
::mediapipe::Status OutputSidePacketImpl::SetInternal(const Packet& packet) {
|
||||
if (!packet_.IsEmpty()) {
|
||||
if (initialized_) {
|
||||
return ::mediapipe::AlreadyExistsErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "Output side packet \"" << name_ << "\" was already set.";
|
||||
}
|
||||
@@ -72,6 +72,7 @@ void OutputSidePacketImpl::AddMirror(
|
||||
}
|
||||
|
||||
packet_ = packet;
|
||||
initialized_ = true;
|
||||
for (const auto& mirror : mirrors_) {
|
||||
mirror.input_side_packet_handler->Set(mirror.id, packet_);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ class OutputSidePacketImpl : public OutputSidePacket {
|
||||
const PacketType* packet_type_;
|
||||
std::function<void(::mediapipe::Status)> error_callback_;
|
||||
Packet packet_;
|
||||
bool initialized_ = false;
|
||||
|
||||
std::vector<Mirror> mirrors_;
|
||||
};
|
||||
|
||||
@@ -653,6 +653,14 @@ Packet PointToForeign(const T* ptr) {
|
||||
return packet_internal::Create(new packet_internal::ForeignHolder<T>(ptr));
|
||||
}
|
||||
|
||||
// Equal Packets refer to the same memory contents, like equal pointers.
|
||||
inline bool operator==(const Packet& p1, const Packet& p2) {
|
||||
return packet_internal::GetHolder(p1) == packet_internal::GetHolder(p2);
|
||||
}
|
||||
inline bool operator!=(const Packet& p1, const Packet& p2) {
|
||||
return !(p1 == p2);
|
||||
}
|
||||
|
||||
} // namespace mediapipe
|
||||
|
||||
#endif // MEDIAPIPE_FRAMEWORK_PACKET_H_
|
||||
|
||||
@@ -28,4 +28,22 @@
|
||||
#define MEDIAPIPE_MOBILE
|
||||
#endif
|
||||
|
||||
#if !defined(MEDIAPIPE_ANDROID) && defined(__ANDROID__)
|
||||
#define MEDIAPIPE_ANDROID
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h" // for TARGET_OS_*
|
||||
#if !defined(MEDIAPIPE_IOS) && !TARGET_OS_OSX
|
||||
#define MEDIAPIPE_IOS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// These platforms do not support OpenGL ES Compute Shaders (v3.1 and up),
|
||||
// but can still run OpenGL ES 3.0 and below.
|
||||
#if !defined(MEDIAPIPE_DISABLE_GL_COMPUTE) && \
|
||||
(defined(__APPLE__) || defined(__EMSCRIPTEN__))
|
||||
#define MEDIAPIPE_DISABLE_GL_COMPUTE
|
||||
#endif
|
||||
|
||||
#endif // MEDIAPIPE_FRAMEWORK_PORT_H_
|
||||
|
||||
@@ -247,25 +247,45 @@ TEST_F(GraphProfilerTestPeer, InitializeConfig) {
|
||||
// Checks histogram_interval_size_usec and num_histogram_intervals.
|
||||
CalculatorProfile actual =
|
||||
GetCalculatorProfilesMap()->find(kDummyTestCalculatorName)->second;
|
||||
ASSERT_EQ(actual.name(), kDummyTestCalculatorName);
|
||||
ASSERT_FALSE(actual.has_open_runtime());
|
||||
ASSERT_FALSE(actual.has_close_runtime());
|
||||
|
||||
ASSERT_EQ(actual.process_runtime().interval_size_usec(), 1000);
|
||||
ASSERT_EQ(actual.process_runtime().num_intervals(), 3);
|
||||
|
||||
ASSERT_EQ(actual.process_input_latency().interval_size_usec(), 1000);
|
||||
ASSERT_EQ(actual.process_input_latency().num_intervals(), 3);
|
||||
|
||||
ASSERT_EQ(actual.process_output_latency().interval_size_usec(), 1000);
|
||||
ASSERT_EQ(actual.process_output_latency().num_intervals(), 3);
|
||||
|
||||
ASSERT_EQ(actual.input_stream_profiles().size(), 1);
|
||||
ASSERT_EQ(actual.input_stream_profiles(0).name(), "input_stream");
|
||||
ASSERT_FALSE(actual.input_stream_profiles(0).back_edge());
|
||||
ASSERT_EQ(actual.input_stream_profiles(0).latency().interval_size_usec(),
|
||||
1000);
|
||||
ASSERT_EQ(actual.input_stream_profiles(0).latency().num_intervals(), 3);
|
||||
EXPECT_THAT(actual, EqualsProto(R"(
|
||||
name: "DummyTestCalculator"
|
||||
process_runtime {
|
||||
total: 0
|
||||
interval_size_usec: 1000
|
||||
num_intervals: 3
|
||||
count: 0
|
||||
count: 0
|
||||
count: 0
|
||||
}
|
||||
process_input_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000
|
||||
num_intervals: 3
|
||||
count: 0
|
||||
count: 0
|
||||
count: 0
|
||||
}
|
||||
process_output_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000
|
||||
num_intervals: 3
|
||||
count: 0
|
||||
count: 0
|
||||
count: 0
|
||||
}
|
||||
input_stream_profiles {
|
||||
name: "input_stream"
|
||||
back_edge: false
|
||||
latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000
|
||||
num_intervals: 3
|
||||
count: 0
|
||||
count: 0
|
||||
count: 0
|
||||
}
|
||||
}
|
||||
)"));
|
||||
}
|
||||
|
||||
// Tests that Initialize() uses the ProfilerConfig in the graph definition.
|
||||
@@ -291,16 +311,17 @@ TEST_F(GraphProfilerTestPeer, InitializeConfigWithoutStreamLatency) {
|
||||
// Checks histogram_interval_size_usec and num_histogram_intervals.
|
||||
CalculatorProfile actual =
|
||||
GetCalculatorProfilesMap()->find(kDummyTestCalculatorName)->second;
|
||||
ASSERT_EQ(actual.name(), kDummyTestCalculatorName);
|
||||
ASSERT_FALSE(actual.has_open_runtime());
|
||||
ASSERT_FALSE(actual.has_close_runtime());
|
||||
|
||||
ASSERT_EQ(actual.process_runtime().interval_size_usec(), 1000);
|
||||
ASSERT_EQ(actual.process_runtime().num_intervals(), 3);
|
||||
|
||||
ASSERT_FALSE(actual.has_process_input_latency());
|
||||
ASSERT_FALSE(actual.has_process_output_latency());
|
||||
ASSERT_EQ(actual.input_stream_profiles().size(), 0);
|
||||
EXPECT_THAT(actual, EqualsProto(R"(
|
||||
name: "DummyTestCalculator"
|
||||
process_runtime {
|
||||
total: 0
|
||||
interval_size_usec: 1000
|
||||
num_intervals: 3
|
||||
count: 0
|
||||
count: 0
|
||||
count: 0
|
||||
}
|
||||
)"));
|
||||
}
|
||||
|
||||
// Tests that Initialize() reads all the configs defined in the graph
|
||||
@@ -633,10 +654,11 @@ TEST_F(GraphProfilerTestPeer, SetOpenRuntime) {
|
||||
simulation_clock->ThreadFinish();
|
||||
|
||||
ASSERT_EQ(profiles.size(), 1);
|
||||
ASSERT_EQ(profiles[0].open_runtime(), 100);
|
||||
ASSERT_FALSE(profiles[0].has_close_runtime());
|
||||
ASSERT_THAT(profiles[0].process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
EXPECT_THAT(profiles[0], Partially(EqualsProto(R"(
|
||||
name: "DummyTestCalculator"
|
||||
open_runtime: 100
|
||||
process_runtime { total: 0 }
|
||||
)")));
|
||||
// Checks packets_info_ map hasn't changed.
|
||||
ASSERT_EQ(GetPacketsInfoMap()->size(), 0);
|
||||
}
|
||||
@@ -688,14 +710,29 @@ TEST_F(GraphProfilerTestPeer, SetOpenRuntimeWithStreamLatency) {
|
||||
ASSERT_EQ(profiles.size(), 2);
|
||||
CalculatorProfile source_profile =
|
||||
GetProfileWithName(profiles, "source_calc");
|
||||
ASSERT_EQ(source_profile.open_runtime(), 150);
|
||||
ASSERT_FALSE(source_profile.has_close_runtime());
|
||||
ASSERT_THAT(source_profile.process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
ASSERT_THAT(source_profile.process_input_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
ASSERT_THAT(source_profile.process_output_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
|
||||
EXPECT_THAT(source_profile, EqualsProto(R"(
|
||||
name: "source_calc"
|
||||
open_runtime: 150
|
||||
process_runtime {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
process_input_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
process_output_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
)"));
|
||||
|
||||
// Check packets_info_ map has been updated.
|
||||
ASSERT_EQ(GetPacketsInfoMap()->size(), 1);
|
||||
@@ -736,11 +773,16 @@ TEST_F(GraphProfilerTestPeer, SetCloseRuntime) {
|
||||
std::vector<CalculatorProfile> profiles = Profiles();
|
||||
simulation_clock->ThreadFinish();
|
||||
|
||||
ASSERT_EQ(profiles.size(), 1);
|
||||
ASSERT_FALSE(profiles[0].open_runtime());
|
||||
ASSERT_EQ(profiles[0].close_runtime(), 100);
|
||||
ASSERT_THAT(profiles[0].process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
EXPECT_THAT(profiles[0], EqualsProto(R"(
|
||||
name: "DummyTestCalculator"
|
||||
close_runtime: 100
|
||||
process_runtime {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
)"));
|
||||
}
|
||||
|
||||
// Tests that SetCloseRuntime() updates |close_runtime| and doesn't affect other
|
||||
@@ -789,11 +831,39 @@ TEST_F(GraphProfilerTestPeer, SetCloseRuntimeWithStreamLatency) {
|
||||
ASSERT_EQ(profiles.size(), 2);
|
||||
CalculatorProfile source_profile =
|
||||
GetProfileWithName(profiles, "source_calc");
|
||||
ASSERT_FALSE(source_profile.open_runtime());
|
||||
ASSERT_EQ(source_profile.close_runtime(), 100);
|
||||
ASSERT_THAT(source_profile.process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
ASSERT_EQ(GetPacketsInfoMap()->size(), 1);
|
||||
|
||||
EXPECT_THAT(source_profile, EqualsProto(R"(
|
||||
name: "source_calc"
|
||||
close_runtime: 100
|
||||
process_runtime {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
process_input_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
process_output_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
input_stream_profiles {
|
||||
name: "input_stream"
|
||||
back_edge: false
|
||||
latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 0
|
||||
}
|
||||
}
|
||||
)"));
|
||||
PacketInfo expected_packet_info = {0,
|
||||
/*production_time_usec=*/1000 + 100,
|
||||
/*source_process_start_usec=*/1000 + 0};
|
||||
@@ -933,10 +1003,15 @@ TEST_F(GraphProfilerTestPeer, AddProcessSample) {
|
||||
simulation_clock->ThreadFinish();
|
||||
|
||||
ASSERT_EQ(profiles.size(), 1);
|
||||
ASSERT_THAT(profiles[0].process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/150, {1}))));
|
||||
ASSERT_FALSE(profiles[0].has_open_runtime());
|
||||
ASSERT_FALSE(profiles[0].has_close_runtime());
|
||||
EXPECT_THAT(profiles[0], EqualsProto(R"(
|
||||
name: "DummyTestCalculator"
|
||||
process_runtime {
|
||||
total: 150
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 1
|
||||
}
|
||||
)"));
|
||||
// Checks packets_info_ map hasn't changed.
|
||||
ASSERT_EQ(GetPacketsInfoMap()->size(), 0);
|
||||
}
|
||||
@@ -985,12 +1060,27 @@ TEST_F(GraphProfilerTestPeer, AddProcessSampleWithStreamLatency) {
|
||||
ASSERT_EQ(profiles.size(), 2);
|
||||
CalculatorProfile source_profile =
|
||||
GetProfileWithName(profiles, "source_calc");
|
||||
ASSERT_THAT(source_profile.process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/150, {1}))));
|
||||
ASSERT_THAT(source_profile.process_input_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {1}))));
|
||||
ASSERT_THAT(source_profile.process_output_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/150, {1}))));
|
||||
|
||||
EXPECT_THAT(profiles[0], Partially(EqualsProto(R"(
|
||||
process_runtime {
|
||||
total: 150
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 1
|
||||
}
|
||||
process_input_latency {
|
||||
total: 0
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 1
|
||||
}
|
||||
process_output_latency {
|
||||
total: 150
|
||||
interval_size_usec: 1000000
|
||||
num_intervals: 1
|
||||
count: 1
|
||||
}
|
||||
)")));
|
||||
|
||||
// Check packets_info_ map has been updated.
|
||||
ASSERT_EQ(GetPacketsInfoMap()->size(), 1);
|
||||
@@ -1019,22 +1109,24 @@ TEST_F(GraphProfilerTestPeer, AddProcessSampleWithStreamLatency) {
|
||||
|
||||
CalculatorProfile consumer_profile =
|
||||
GetProfileWithName(profiles, "consumer_calc");
|
||||
ASSERT_THAT(consumer_profile.process_runtime(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/250, {1}))));
|
||||
ASSERT_THAT(consumer_profile.process_input_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(
|
||||
/*total=*/2000 - when_source_started, {1}))));
|
||||
ASSERT_THAT(consumer_profile.process_output_latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(
|
||||
/*total=*/2000 + 250 - when_source_started, {1}))));
|
||||
ASSERT_EQ(consumer_profile.input_stream_profiles().size(), 2);
|
||||
// For "stream_0" should have not changed since it was empty.
|
||||
ASSERT_THAT(consumer_profile.input_stream_profiles(0).latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(/*total=*/0, {0}))));
|
||||
// For "stream_1"
|
||||
ASSERT_THAT(consumer_profile.input_stream_profiles(1).latency(),
|
||||
Partially(EqualsProto(CreateTimeHistogram(
|
||||
/*total=*/2000 - when_source_finished, {1}))));
|
||||
|
||||
// process input latency total = 2000 (end) - 1000 (when source started) =
|
||||
// 1000 process output latency total = 2000 (end) + 250 - 1000 (when source
|
||||
// started) = 1250 For "stream_0" should have not changed since it was empty.
|
||||
// For "stream_1" = 2000 (end) - 1250 (when source finished) = 850
|
||||
EXPECT_THAT(consumer_profile, Partially(EqualsProto(R"(
|
||||
name: "consumer_calc"
|
||||
process_input_latency { total: 1000 }
|
||||
process_output_latency { total: 1250 }
|
||||
input_stream_profiles {
|
||||
name: "stream_0"
|
||||
latency { total: 0 }
|
||||
}
|
||||
input_stream_profiles {
|
||||
name: "stream_1"
|
||||
latency { total: 850 }
|
||||
}
|
||||
)")));
|
||||
|
||||
// Check packets_info_ map for PacketId({"stream_1", 100}) should not yet be
|
||||
// garbage collected.
|
||||
|
||||
@@ -39,9 +39,20 @@ inline const void* GetPacketDataId(const HolderBase* holder) {
|
||||
struct TraceEvent {
|
||||
using EventType = GraphTrace::EventType;
|
||||
// GraphTrace::EventType constants, repeated here to match GraphProfilerStub.
|
||||
static const EventType UNKNOWN, OPEN, PROCESS, CLOSE, NOT_READY,
|
||||
READY_FOR_PROCESS, READY_FOR_CLOSE, THROTTLED, UNTHROTTLED, CPU_TASK_USER,
|
||||
CPU_TASK_SYSTEM, GPU_TASK, DSP_TASK, TPU_TASK;
|
||||
static constexpr EventType UNKNOWN = GraphTrace::UNKNOWN;
|
||||
static constexpr EventType OPEN = GraphTrace::OPEN;
|
||||
static constexpr EventType PROCESS = GraphTrace::PROCESS;
|
||||
static constexpr EventType CLOSE = GraphTrace::CLOSE;
|
||||
static constexpr EventType NOT_READY = GraphTrace::NOT_READY;
|
||||
static constexpr EventType READY_FOR_PROCESS = GraphTrace::READY_FOR_PROCESS;
|
||||
static constexpr EventType READY_FOR_CLOSE = GraphTrace::READY_FOR_CLOSE;
|
||||
static constexpr EventType THROTTLED = GraphTrace::THROTTLED;
|
||||
static constexpr EventType UNTHROTTLED = GraphTrace::UNTHROTTLED;
|
||||
static constexpr EventType CPU_TASK_USER = GraphTrace::CPU_TASK_USER;
|
||||
static constexpr EventType CPU_TASK_SYSTEM = GraphTrace::CPU_TASK_SYSTEM;
|
||||
static constexpr EventType GPU_TASK = GraphTrace::GPU_TASK;
|
||||
static constexpr EventType DSP_TASK = GraphTrace::DSP_TASK;
|
||||
static constexpr EventType TPU_TASK = GraphTrace::TPU_TASK;
|
||||
absl::Time event_time;
|
||||
EventType event_type = UNKNOWN;
|
||||
bool is_finish = false;
|
||||
|
||||
@@ -385,21 +385,21 @@ void TraceBuilder::CreateLog(const TraceBuffer& buffer, absl::Time begin_time,
|
||||
}
|
||||
void TraceBuilder::Clear() { impl_->Clear(); }
|
||||
|
||||
// Defined here since inline constants fail to link in android builds.
|
||||
const TraceEvent::EventType //
|
||||
TraceEvent::UNKNOWN = GraphTrace::UNKNOWN,
|
||||
TraceEvent::OPEN = GraphTrace::OPEN,
|
||||
TraceEvent::PROCESS = GraphTrace::PROCESS,
|
||||
TraceEvent::CLOSE = GraphTrace::CLOSE,
|
||||
TraceEvent::NOT_READY = GraphTrace::NOT_READY,
|
||||
TraceEvent::READY_FOR_PROCESS = GraphTrace::READY_FOR_PROCESS,
|
||||
TraceEvent::READY_FOR_CLOSE = GraphTrace::READY_FOR_CLOSE,
|
||||
TraceEvent::THROTTLED = GraphTrace::THROTTLED,
|
||||
TraceEvent::UNTHROTTLED = GraphTrace::UNTHROTTLED,
|
||||
TraceEvent::CPU_TASK_USER = GraphTrace::CPU_TASK_USER,
|
||||
TraceEvent::CPU_TASK_SYSTEM = GraphTrace::CPU_TASK_SYSTEM,
|
||||
TraceEvent::GPU_TASK = GraphTrace::GPU_TASK,
|
||||
TraceEvent::DSP_TASK = GraphTrace::DSP_TASK,
|
||||
TraceEvent::TPU_TASK = GraphTrace::TPU_TASK;
|
||||
// Defined here since constexpr requires out-of-class definition until C++17.
|
||||
const TraceEvent::EventType //
|
||||
TraceEvent::UNKNOWN, //
|
||||
TraceEvent::OPEN, //
|
||||
TraceEvent::PROCESS, //
|
||||
TraceEvent::CLOSE, //
|
||||
TraceEvent::NOT_READY, //
|
||||
TraceEvent::READY_FOR_PROCESS, //
|
||||
TraceEvent::READY_FOR_CLOSE, //
|
||||
TraceEvent::THROTTLED, //
|
||||
TraceEvent::UNTHROTTLED, //
|
||||
TraceEvent::CPU_TASK_USER, //
|
||||
TraceEvent::CPU_TASK_SYSTEM, //
|
||||
TraceEvent::GPU_TASK, //
|
||||
TraceEvent::DSP_TASK, //
|
||||
TraceEvent::TPU_TASK;
|
||||
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -127,6 +127,11 @@ class TagMap {
|
||||
std::vector<std::string> names_;
|
||||
};
|
||||
|
||||
// Equal TagData structs define equal id ranges.
|
||||
inline bool operator==(const TagMap::TagData& d1, const TagMap::TagData& d2) {
|
||||
return d1.id == d2.id && d1.count == d2.count;
|
||||
}
|
||||
|
||||
} // namespace tool
|
||||
} // namespace mediapipe
|
||||
|
||||
|
||||
@@ -567,6 +567,10 @@ class TemplateExpanderImpl {
|
||||
result = AsDict(args);
|
||||
} else if (expr.op() == "list") {
|
||||
result = AsList(args);
|
||||
} else if (expr.op() == "size") {
|
||||
return AsArgument(static_cast<double>(
|
||||
args[0].has_dict() ? args[0].mutable_dict()->arg_size()
|
||||
: args[0].mutable_element()->size()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1318,8 +1318,8 @@ bool IsInfixOperator(const std::string& token) {
|
||||
// A function-style operator, including a for or if expression.
|
||||
bool IsFunctionOperator(const std::string& token) {
|
||||
static auto kTokens = new std::set<std::string>{
|
||||
"min", "max", "for", "if", "!",
|
||||
"concat", "lowercase", "uppercase", "dict", "list",
|
||||
"min", "max", "for", "if", "!", "concat",
|
||||
"lowercase", "uppercase", "size", "dict", "list",
|
||||
};
|
||||
return kTokens->count(token) > 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user