Project import generated by Copybara.
GitOrigin-RevId: 1e13be30e2c6838d4a2ff768a39c414bc80534bb
This commit is contained in:
committed by
Sebastian Schmidt
parent
63e679d99c
commit
4dc4b19ddb
@@ -151,6 +151,16 @@ mediapipe_proto_library(
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_proto_library(
|
||||
name = "get_vector_item_calculator_proto",
|
||||
srcs = ["get_vector_item_calculator.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_options_proto",
|
||||
"//mediapipe/framework:calculator_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "add_header_calculator",
|
||||
srcs = ["add_header_calculator.cc"],
|
||||
@@ -561,6 +571,7 @@ cc_test(
|
||||
name = "packet_cloner_calculator_test",
|
||||
srcs = ["packet_cloner_calculator_test.cc"],
|
||||
deps = [
|
||||
":gate_calculator",
|
||||
":packet_cloner_calculator",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:timestamp",
|
||||
@@ -1281,6 +1292,7 @@ cc_library(
|
||||
hdrs = ["get_vector_item_calculator.h"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":get_vector_item_calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:packet",
|
||||
"//mediapipe/framework/api2:node",
|
||||
@@ -1293,6 +1305,20 @@ cc_library(
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "get_vector_item_calculator_test",
|
||||
srcs = ["get_vector_item_calculator_test.cc"],
|
||||
deps = [
|
||||
":get_vector_item_calculator",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:calculator_runner",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "vector_size_calculator",
|
||||
srcs = ["vector_size_calculator.cc"],
|
||||
@@ -1307,3 +1333,54 @@ cc_library(
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "packet_sequencer_calculator",
|
||||
srcs = ["packet_sequencer_calculator.cc"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework/api2:contract",
|
||||
"//mediapipe/framework/api2:node",
|
||||
"//mediapipe/framework/api2:packet",
|
||||
"//mediapipe/framework/api2:port",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/framework/stream_handler:immediate_input_stream_handler",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "packet_sequencer_calculator_test",
|
||||
srcs = ["packet_sequencer_calculator_test.cc"],
|
||||
deps = [
|
||||
":packet_sequencer_calculator",
|
||||
"//mediapipe/calculators/core:pass_through_calculator",
|
||||
"//mediapipe/framework:calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:subgraph",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"//mediapipe/framework/port:logging",
|
||||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "merge_to_vector_calculator",
|
||||
srcs = ["merge_to_vector_calculator.cc"],
|
||||
hdrs = ["merge_to_vector_calculator.h"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework/api2:node",
|
||||
"//mediapipe/framework/api2:port",
|
||||
"//mediapipe/framework/formats:image",
|
||||
"@com_google_absl//absl/status",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message ClipVectorSizeCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional ClipVectorSizeCalculatorOptions ext = 274674998;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message ConcatenateVectorCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional ConcatenateVectorCalculatorOptions ext = 259397839;
|
||||
|
||||
@@ -20,8 +20,6 @@ import "mediapipe/framework/calculator.proto";
|
||||
import "mediapipe/framework/formats/classification.proto";
|
||||
import "mediapipe/framework/formats/landmark.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message ConstantSidePacketCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional ConstantSidePacketCalculatorOptions ext = 291214597;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message DequantizeByteArrayCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional DequantizeByteArrayCalculatorOptions ext = 272316343;
|
||||
|
||||
@@ -18,7 +18,8 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
option java_package = "com.google.mediapipe.calculator.proto";
|
||||
option java_outer_classname = "FlowLimiterCalculatorProto";
|
||||
|
||||
message FlowLimiterCalculatorOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message GateCalculatorOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional GateCalculatorOptions ext = 261754847;
|
||||
|
||||
@@ -17,22 +17,24 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "mediapipe/calculators/core/get_vector_item_calculator.pb.h"
|
||||
#include "mediapipe/framework/api2/node.h"
|
||||
#include "mediapipe/framework/api2/port.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/packet.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace api2 {
|
||||
|
||||
// A calcutlator to return an item from the vector by its index.
|
||||
// A calculator to return an item from the vector by its index.
|
||||
// Item index can be specified through INDEX stream and/or calculator options.
|
||||
// INDEX stream takes precedence over options.
|
||||
//
|
||||
// Inputs:
|
||||
// VECTOR - std::vector<T>
|
||||
// Vector to take an item from.
|
||||
// INDEX - int
|
||||
// INDEX [OPTIONAL] - int
|
||||
// Index of the item to return.
|
||||
//
|
||||
// Outputs:
|
||||
@@ -45,26 +47,47 @@ namespace api2 {
|
||||
// input_stream: "VECTOR:vector"
|
||||
// input_stream: "INDEX:index"
|
||||
// input_stream: "ITEM:item"
|
||||
// options {
|
||||
// [mediapipe.GetVectorItemCalculatorOptions.ext] {
|
||||
// item_index: 5
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
template <typename T>
|
||||
class GetVectorItemCalculator : public Node {
|
||||
public:
|
||||
static constexpr Input<std::vector<T>> kIn{"VECTOR"};
|
||||
static constexpr Input<int> kIdx{"INDEX"};
|
||||
static constexpr Input<int>::Optional kIdx{"INDEX"};
|
||||
static constexpr Output<T> kOut{"ITEM"};
|
||||
|
||||
MEDIAPIPE_NODE_CONTRACT(kIn, kIdx, kOut);
|
||||
|
||||
absl::Status Open(CalculatorContext* cc) final {
|
||||
auto& options = cc->Options<mediapipe::GetVectorItemCalculatorOptions>();
|
||||
RET_CHECK(kIdx(cc).IsConnected() || options.has_item_index());
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Process(CalculatorContext* cc) final {
|
||||
if (kIn(cc).IsEmpty() || kIdx(cc).IsEmpty()) {
|
||||
if (kIn(cc).IsEmpty()) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
const std::vector<T>& items = kIn(cc).Get();
|
||||
const int idx = kIdx(cc).Get();
|
||||
const auto& options =
|
||||
cc->Options<mediapipe::GetVectorItemCalculatorOptions>();
|
||||
|
||||
RET_CHECK_LT(idx, items.size());
|
||||
int idx = 0;
|
||||
if (kIdx(cc).IsConnected() && !kIdx(cc).IsEmpty()) {
|
||||
idx = kIdx(cc).Get();
|
||||
} else if (options.has_item_index()) {
|
||||
idx = options.item_index();
|
||||
} else {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
RET_CHECK(idx >= 0 && idx < items.size());
|
||||
kOut(cc).Send(items[idx]);
|
||||
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
message GetVectorItemCalculatorOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional GetVectorItemCalculatorOptions ext = 463538543;
|
||||
}
|
||||
|
||||
// Index of vector item to get. INDEX input stream can be used instead, or to
|
||||
// override.
|
||||
optional int32 item_index = 1;
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
#include "mediapipe/calculators/core/get_vector_item_calculator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/calculator_runner.h"
|
||||
#include "mediapipe/framework/port/gmock.h"
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
MATCHER_P(IntPacket, value, "") {
|
||||
return testing::Value(arg.template Get<int>(), testing::Eq(value));
|
||||
}
|
||||
|
||||
MATCHER_P(TimestampValue, value, "") {
|
||||
return testing::Value(arg.Timestamp(), testing::Eq(Timestamp(value)));
|
||||
}
|
||||
|
||||
using TestGetIntVectorItemCalculator = api2::GetVectorItemCalculator<int>;
|
||||
MEDIAPIPE_REGISTER_NODE(TestGetIntVectorItemCalculator);
|
||||
|
||||
CalculatorRunner MakeRunnerWithStream() {
|
||||
return CalculatorRunner(R"(
|
||||
calculator: "TestGetIntVectorItemCalculator"
|
||||
input_stream: "VECTOR:vector_stream"
|
||||
input_stream: "INDEX:index_stream"
|
||||
output_stream: "ITEM:item_stream"
|
||||
)");
|
||||
}
|
||||
|
||||
CalculatorRunner MakeRunnerWithOptions(int set_index) {
|
||||
return CalculatorRunner(absl::StrFormat(R"(
|
||||
calculator: "TestGetIntVectorItemCalculator"
|
||||
input_stream: "VECTOR:vector_stream"
|
||||
output_stream: "ITEM:item_stream"
|
||||
options {
|
||||
[mediapipe.GetVectorItemCalculatorOptions.ext] {
|
||||
item_index: %d
|
||||
}
|
||||
}
|
||||
)",
|
||||
set_index));
|
||||
}
|
||||
|
||||
void AddInputVector(CalculatorRunner& runner, const std::vector<int>& inputs,
|
||||
int timestamp) {
|
||||
runner.MutableInputs()->Tag("VECTOR").packets.push_back(
|
||||
MakePacket<std::vector<int>>(inputs).At(Timestamp(timestamp)));
|
||||
}
|
||||
|
||||
void AddInputIndex(CalculatorRunner& runner, int index, int timestamp) {
|
||||
runner.MutableInputs()->Tag("INDEX").packets.push_back(
|
||||
MakePacket<int>(index).At(Timestamp(timestamp)));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, EmptyIndexStreamNoOutput) {
|
||||
CalculatorRunner runner = MakeRunnerWithStream();
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_EQ(0, outputs.size());
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, SuccessfulExtractionIndexStream) {
|
||||
CalculatorRunner runner = MakeRunnerWithStream();
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
const int index = 1;
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
AddInputIndex(runner, index, 1);
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_THAT(outputs, testing::ElementsAre(IntPacket(inputs[index])));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, SuccessfulExtractionIndexProto) {
|
||||
const int index = 2;
|
||||
CalculatorRunner runner = MakeRunnerWithOptions(index);
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_THAT(outputs, testing::ElementsAre(IntPacket(inputs[index])));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, StreamIsPreferred) {
|
||||
CalculatorRunner runner(R"(
|
||||
calculator: "TestGetIntVectorItemCalculator"
|
||||
input_stream: "VECTOR:vector_stream"
|
||||
input_stream: "INDEX:index_stream"
|
||||
output_stream: "ITEM:item_stream"
|
||||
options {
|
||||
[mediapipe.GetVectorItemCalculatorOptions.ext] {
|
||||
item_index: 2
|
||||
}
|
||||
}
|
||||
)");
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
const int stream_index = 0;
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
AddInputIndex(runner, stream_index, 1);
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_THAT(outputs, testing::ElementsAre(IntPacket(inputs[stream_index])));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, NoStreamNorOptionsExpectFail) {
|
||||
CalculatorRunner runner(R"(
|
||||
calculator: "TestGetIntVectorItemCalculator"
|
||||
input_stream: "VECTOR:vector_stream"
|
||||
output_stream: "ITEM:item_stream"
|
||||
)");
|
||||
|
||||
absl::Status status = runner.Run();
|
||||
ASSERT_FALSE(status.ok());
|
||||
EXPECT_THAT(
|
||||
status.message(),
|
||||
testing::HasSubstr("kIdx(cc).IsConnected() || options.has_item_index()"));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, StreamIndexBoundsCheckFail1) {
|
||||
CalculatorRunner runner = MakeRunnerWithStream();
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
const int try_index = -1;
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
AddInputIndex(runner, try_index, 1);
|
||||
|
||||
absl::Status status = runner.Run();
|
||||
ASSERT_FALSE(status.ok());
|
||||
EXPECT_THAT(status.message(),
|
||||
testing::HasSubstr("idx >= 0 && idx < items.size()"));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, StreamIndexBoundsCheckFail2) {
|
||||
CalculatorRunner runner = MakeRunnerWithStream();
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
const int try_index = 3;
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
AddInputIndex(runner, try_index, 1);
|
||||
|
||||
absl::Status status = runner.Run();
|
||||
ASSERT_FALSE(status.ok());
|
||||
EXPECT_THAT(status.message(),
|
||||
testing::HasSubstr("idx >= 0 && idx < items.size()"));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, OptionsIndexBoundsCheckFail1) {
|
||||
const int try_index = -1;
|
||||
CalculatorRunner runner = MakeRunnerWithOptions(try_index);
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
|
||||
absl::Status status = runner.Run();
|
||||
ASSERT_FALSE(status.ok());
|
||||
EXPECT_THAT(status.message(),
|
||||
testing::HasSubstr("idx >= 0 && idx < items.size()"));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, OptionsIndexBoundsCheckFail2) {
|
||||
const int try_index = 3;
|
||||
CalculatorRunner runner = MakeRunnerWithOptions(try_index);
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
|
||||
AddInputVector(runner, inputs, 1);
|
||||
|
||||
absl::Status status = runner.Run();
|
||||
ASSERT_FALSE(status.ok());
|
||||
EXPECT_THAT(status.message(),
|
||||
testing::HasSubstr("idx >= 0 && idx < items.size()"));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, IndexStreamTwoTimestamps) {
|
||||
CalculatorRunner runner = MakeRunnerWithStream();
|
||||
|
||||
{
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
const int index = 1;
|
||||
AddInputVector(runner, inputs, 1);
|
||||
AddInputIndex(runner, index, 1);
|
||||
}
|
||||
{
|
||||
const std::vector<int> inputs = {5, 6, 7, 8};
|
||||
const int index = 3;
|
||||
AddInputVector(runner, inputs, 2);
|
||||
AddInputIndex(runner, index, 2);
|
||||
}
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_THAT(outputs, testing::ElementsAre(IntPacket(2), IntPacket(8)));
|
||||
EXPECT_THAT(outputs,
|
||||
testing::ElementsAre(TimestampValue(1), TimestampValue(2)));
|
||||
}
|
||||
|
||||
TEST(TestGetIntVectorItemCalculatorTest, IndexOptionsTwoTimestamps) {
|
||||
const int static_index = 2;
|
||||
CalculatorRunner runner = MakeRunnerWithOptions(static_index);
|
||||
|
||||
{
|
||||
const std::vector<int> inputs = {1, 2, 3};
|
||||
AddInputVector(runner, inputs, 1);
|
||||
}
|
||||
{
|
||||
const std::vector<int> inputs = {5, 6, 7, 8};
|
||||
AddInputVector(runner, inputs, 2);
|
||||
}
|
||||
MP_ASSERT_OK(runner.Run());
|
||||
|
||||
const std::vector<Packet>& outputs = runner.Outputs().Tag("ITEM").packets;
|
||||
EXPECT_THAT(outputs, testing::ElementsAre(IntPacket(3), IntPacket(7)));
|
||||
EXPECT_THAT(outputs,
|
||||
testing::ElementsAre(TimestampValue(1), TimestampValue(2)));
|
||||
}
|
||||
|
||||
} // namespace mediapipe
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message GraphProfileCalculatorOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional GraphProfileCalculatorOptions ext = 367481815;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Copyright 2022 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
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/calculators/core/merge_to_vector_calculator.h"
|
||||
|
||||
#include "mediapipe/framework/formats/image.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace api2 {
|
||||
|
||||
typedef MergeToVectorCalculator<mediapipe::Image> MergeImagesToVectorCalculator;
|
||||
MEDIAPIPE_REGISTER_NODE(MergeImagesToVectorCalculator);
|
||||
|
||||
} // namespace api2
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright 2022 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
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_CALCULATORS_CORE_MERGE_TO_VECTOR_CALCULATOR_H_
|
||||
#define MEDIAPIPE_CALCULATORS_CORE_MERGE_TO_VECTOR_CALCULATOR_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "mediapipe/framework/api2/node.h"
|
||||
#include "mediapipe/framework/api2/port.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace api2 {
|
||||
|
||||
template <typename T>
|
||||
class MergeToVectorCalculator : public Node {
|
||||
public:
|
||||
static constexpr typename Input<T>::Multiple kIn{""};
|
||||
static constexpr Output<std::vector<T>> kOut{""};
|
||||
|
||||
MEDIAPIPE_NODE_CONTRACT(kIn, kOut);
|
||||
|
||||
static absl::Status UpdateContract(CalculatorContract* cc) {
|
||||
RET_CHECK_GT(kIn(cc).Count(), 0) << "Needs at least one input stream";
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Process(CalculatorContext* cc) {
|
||||
const int input_num = kIn(cc).Count();
|
||||
std::vector<T> output_vector(input_num);
|
||||
std::transform(kIn(cc).begin(), kIn(cc).end(), output_vector.begin(),
|
||||
[](const auto& elem) -> T { return elem.Get(); });
|
||||
kOut(cc).Send(output_vector);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace api2
|
||||
} // namespace mediapipe
|
||||
|
||||
#endif // MEDIAPIPE_CALCULATORS_CORE_MERGE_TO_VECTOR_CALCULATOR_H_
|
||||
@@ -58,6 +58,7 @@ namespace mediapipe {
|
||||
class PacketClonerCalculator : public CalculatorBase {
|
||||
public:
|
||||
static absl::Status GetContract(CalculatorContract* cc) {
|
||||
cc->SetProcessTimestampBounds(true);
|
||||
const Ids ids = GetIds(*cc);
|
||||
for (const auto& in_out : ids.inputs_outputs) {
|
||||
auto& input = cc->Inputs().Get(in_out.in);
|
||||
@@ -101,30 +102,30 @@ class PacketClonerCalculator : public CalculatorBase {
|
||||
}
|
||||
}
|
||||
|
||||
bool has_all_inputs = HasAllInputs();
|
||||
// Output according to the TICK signal.
|
||||
if (!cc->Inputs().Get(ids_.tick_id).IsEmpty()) {
|
||||
if (output_only_when_all_inputs_received_) {
|
||||
// Return if one of the input is null.
|
||||
for (int i = 0; i < ids_.inputs_outputs.size(); ++i) {
|
||||
if (current_[i].IsEmpty()) {
|
||||
if (output_empty_packets_before_all_inputs_received_) {
|
||||
SetAllNextTimestampBounds(cc);
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cc->Inputs().Get(ids_.tick_id).IsEmpty() &&
|
||||
(has_all_inputs || !output_only_when_all_inputs_received_)) {
|
||||
// Output each stream.
|
||||
for (int i = 0; i < ids_.inputs_outputs.size(); ++i) {
|
||||
auto& output = cc->Outputs().Get(ids_.inputs_outputs[i].out);
|
||||
if (!current_[i].IsEmpty()) {
|
||||
output.AddPacket(current_[i].At(cc->InputTimestamp()));
|
||||
} else {
|
||||
output.SetNextTimestampBound(
|
||||
cc->InputTimestamp().NextAllowedInStream());
|
||||
output.AddPacket(current_[i].At(
|
||||
cc->Inputs().Get(ids_.tick_id).Value().Timestamp()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set timestamp bounds according to the TICK signal.
|
||||
bool tick_updated = cc->Inputs().Get(ids_.tick_id).Value().Timestamp() ==
|
||||
cc->InputTimestamp();
|
||||
bool producing_output = has_all_inputs ||
|
||||
output_empty_packets_before_all_inputs_received_ ||
|
||||
!output_only_when_all_inputs_received_;
|
||||
if (tick_updated && producing_output) {
|
||||
SetAllNextTimestampBounds(cc);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -165,6 +166,15 @@ class PacketClonerCalculator : public CalculatorBase {
|
||||
}
|
||||
}
|
||||
|
||||
bool HasAllInputs() {
|
||||
for (int i = 0; i < ids_.inputs_outputs.size(); ++i) {
|
||||
if (current_[i].IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Packet> current_;
|
||||
Ids ids_;
|
||||
bool output_only_when_all_inputs_received_;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message PacketClonerCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional PacketClonerCalculatorOptions ext = 258872085;
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace {
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::IsTrue;
|
||||
using ::testing::Value;
|
||||
|
||||
MATCHER_P2(IntPacket, value, ts, "") {
|
||||
@@ -45,6 +46,11 @@ MATCHER_P2(FloatPacket, value, ts, "") {
|
||||
Value(arg.Timestamp(), Eq(Timestamp(ts)));
|
||||
}
|
||||
|
||||
MATCHER_P(EmptyPacket, ts, "") {
|
||||
return Value(arg.IsEmpty(), IsTrue()) &&
|
||||
Value(arg.Timestamp(), Eq(Timestamp(ts)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
absl::Status SendPacket(const std::string& input_name, T value, int ts,
|
||||
CalculatorGraph& graph) {
|
||||
@@ -342,6 +348,105 @@ TEST_P(PacketClonerCalculatorTest,
|
||||
FloatPacket(40.0f, 40000))));
|
||||
}
|
||||
|
||||
class PacketClonerCalculatorGatedInputTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
CalculatorGraphConfig graph_config =
|
||||
ParseTextProtoOrDie<CalculatorGraphConfig>([&]() {
|
||||
return R"pb(
|
||||
input_stream: 'input'
|
||||
input_stream: 'input_enabled'
|
||||
input_stream: 'tick'
|
||||
input_stream: 'tick_enabled'
|
||||
node {
|
||||
calculator: 'GateCalculator'
|
||||
input_stream: 'tick'
|
||||
input_stream: 'ALLOW:tick_enabled'
|
||||
output_stream: 'tick_gated'
|
||||
}
|
||||
node {
|
||||
calculator: 'GateCalculator'
|
||||
input_stream: 'input'
|
||||
input_stream: 'ALLOW:input_enabled'
|
||||
output_stream: 'input_gated'
|
||||
}
|
||||
node {
|
||||
calculator: 'PacketClonerCalculator'
|
||||
input_stream: 'input_gated'
|
||||
input_stream: 'TICK:tick_gated'
|
||||
output_stream: 'output'
|
||||
})pb";
|
||||
}());
|
||||
|
||||
MP_ASSERT_OK(graph.Initialize(graph_config, {}));
|
||||
MP_ASSERT_OK(graph.ObserveOutputStream(
|
||||
"output",
|
||||
[this](Packet const& packet) {
|
||||
output.push_back(packet);
|
||||
return absl::OkStatus();
|
||||
},
|
||||
true));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
}
|
||||
|
||||
CalculatorGraph graph;
|
||||
std::vector<Packet> output;
|
||||
};
|
||||
|
||||
TEST_F(PacketClonerCalculatorGatedInputTest,
|
||||
PropagatesTimestampBoundsWithEmptyInput) {
|
||||
MP_ASSERT_OK(SendPacket("tick_enabled", false, /*ts=*/100, graph));
|
||||
MP_ASSERT_OK(SendPacket("tick", 0, /*ts=*/100, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", false, /*ts=*/200, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 1, /*ts=*/200, graph));
|
||||
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
EXPECT_THAT(output, ElementsAre(EmptyPacket(100)));
|
||||
}
|
||||
|
||||
TEST_F(PacketClonerCalculatorGatedInputTest,
|
||||
PropagatesTimestampBoundsWithInput) {
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", true, /*ts=*/100, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 1, /*ts=*/100, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("tick_enabled", true, /*ts=*/100, graph));
|
||||
MP_ASSERT_OK(SendPacket("tick", 0, /*ts=*/100, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("tick_enabled", false, /*ts=*/110, graph));
|
||||
MP_ASSERT_OK(SendPacket("tick", 0, /*ts=*/110, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", false, /*ts=*/200, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 2, /*ts=*/200, graph));
|
||||
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
EXPECT_THAT(output, ElementsAre(IntPacket(1, 100), EmptyPacket(110)));
|
||||
}
|
||||
|
||||
TEST_F(PacketClonerCalculatorGatedInputTest,
|
||||
PropagatesTimestampBoundsFromTick) {
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", true, /*ts=*/100, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 1, /*ts=*/100, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("tick_enabled", true, /*ts=*/100, graph));
|
||||
MP_ASSERT_OK(SendPacket("tick", 0, /*ts=*/100, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", true, /*ts=*/110, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 2, /*ts=*/110, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("tick_enabled", false, /*ts=*/200, graph));
|
||||
MP_ASSERT_OK(SendPacket("tick", 0, /*ts=*/200, graph));
|
||||
|
||||
MP_ASSERT_OK(SendPacket("input_enabled", false, /*ts=*/200, graph));
|
||||
MP_ASSERT_OK(SendPacket("input", 2, /*ts=*/200, graph));
|
||||
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
EXPECT_THAT(output, ElementsAre(IntPacket(1, 100), EmptyPacket(200)));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(PacketClonerCalculator, PacketClonerCalculatorTest,
|
||||
testing::ValuesIn({Params{.use_tick_tag = false},
|
||||
Params{.use_tick_tag = true}}));
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message PacketResamplerCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional PacketResamplerCalculatorOptions ext = 95743844;
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright 2022 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 "mediapipe/framework/api2/contract.h"
|
||||
#include "mediapipe/framework/api2/node.h"
|
||||
#include "mediapipe/framework/api2/packet.h"
|
||||
#include "mediapipe/framework/api2/port.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace api2 {
|
||||
|
||||
// This calculator assigns a timestamp to each "INPUT" packet reflecting
|
||||
// the most recent "TICK" timestamp.
|
||||
//
|
||||
// Each "TICK" timestamp is propagated as a settled "OUTPUT" timestamp.
|
||||
// This allows "TICK" packets to be processed right away.
|
||||
// When an "INPUT" packet arrives, it is sent to the "OUTPUT" stream with
|
||||
// the next unsettled "OUTPUT" timestamp, which is normally one greater than
|
||||
// the most recent "TICK" timestamp.
|
||||
//
|
||||
// If a "TICK" packet and an "INPUT" packet arrive together, the "OUTPUT"
|
||||
// packet timestamp is derived from the previous "TICK" timestamp,
|
||||
// and the new "OUTPUT" bound is derived from the current "TICK" timestamp.
|
||||
// This allows the current "INPUT" packet to cover the current "TICK" timestamp.
|
||||
//
|
||||
// Example config:
|
||||
// node {
|
||||
// calculator: "PacketSequencerCalculator"
|
||||
// input_stream: "INPUT:switch_selection"
|
||||
// input_stream: "TICK:input_image"
|
||||
// input_stream: "TICK:input_audio"
|
||||
// output_stream: "OUTPUT:switch_selection_timed"
|
||||
// }
|
||||
//
|
||||
class PacketSequencerCalculator : public Node {
|
||||
public:
|
||||
static constexpr Input<AnyType>::Multiple kInput{"INPUT"};
|
||||
static constexpr Input<AnyType>::Multiple kTick{"TICK"};
|
||||
static constexpr Output<AnyType>::Multiple kOutput{"OUTPUT"};
|
||||
|
||||
MEDIAPIPE_NODE_CONTRACT(kInput, kTick, kOutput,
|
||||
StreamHandler("ImmediateInputStreamHandler"),
|
||||
TimestampChange::Arbitrary());
|
||||
|
||||
static absl::Status UpdateContract(CalculatorContract* cc) {
|
||||
RET_CHECK_EQ(kInput(cc).Count(), kOutput(cc).Count());
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Process(CalculatorContext* cc) final {
|
||||
// Pass through any input packets at the output stream bound.
|
||||
for (int i = 0; i < kInput(cc).Count(); ++i) {
|
||||
Timestamp stream_bound = kOutput(cc)[i].NextTimestampBound();
|
||||
const PacketBase input_packet = kInput(cc)[i].packet();
|
||||
if (!input_packet.IsEmpty()) {
|
||||
Timestamp output_ts = std::max(Timestamp::Min(), stream_bound);
|
||||
kOutput(cc)[i].Send(input_packet.At(output_ts));
|
||||
}
|
||||
}
|
||||
|
||||
// Find the new tick timestamp, if any.
|
||||
Timestamp tick_ts = Timestamp::Min();
|
||||
for (int i = 0; i < kTick(cc).Count(); ++i) {
|
||||
const PacketBase& tick_packet = kTick(cc)[i].packet();
|
||||
// For either an input packet or an empty input stream,
|
||||
// the packet timestamp indicates the latest "settled timestamp",
|
||||
// and when it arrives it equals the InputTimestamp().
|
||||
if (tick_packet.timestamp() == cc->InputTimestamp()) {
|
||||
tick_ts = std::max(tick_ts, tick_packet.timestamp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance all output stream bounds past the tick timestamp.
|
||||
for (int i = 0; i < kInput(cc).Count(); ++i) {
|
||||
Timestamp stream_bound = kOutput(cc)[i].NextTimestampBound();
|
||||
if (tick_ts >= stream_bound) {
|
||||
kOutput(cc)[i].SetNextTimestampBound(tick_ts.NextAllowedInStream());
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
};
|
||||
|
||||
MEDIAPIPE_REGISTER_NODE(PacketSequencerCalculator);
|
||||
} // namespace api2
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2022 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 <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/calculator.pb.h"
|
||||
#include "mediapipe/framework/calculator_framework.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/ret_check.h"
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
|
||||
// Returns a CalculatorGraph to run a single calculator.
|
||||
CalculatorGraph BuildCalculatorGraph(CalculatorGraphConfig::Node node_config) {
|
||||
CalculatorGraphConfig config;
|
||||
*config.add_node() = node_config;
|
||||
*config.mutable_input_stream() = node_config.input_stream();
|
||||
*config.mutable_output_stream() = node_config.output_stream();
|
||||
*config.mutable_input_side_packet() = node_config.input_side_packet();
|
||||
*config.mutable_output_side_packet() = node_config.output_side_packet();
|
||||
return CalculatorGraph(config);
|
||||
}
|
||||
|
||||
// Creates a string packet.
|
||||
Packet pack(std::string data, int timestamp) {
|
||||
return MakePacket<std::string>(data).At(Timestamp(timestamp));
|
||||
}
|
||||
|
||||
// Tests showing packet timestamp synchronization through
|
||||
// PacketSequencerCalculator.
|
||||
class PacketSequencerCalculatorTest : public ::testing::Test {
|
||||
protected:
|
||||
PacketSequencerCalculatorTest() {}
|
||||
~PacketSequencerCalculatorTest() override {}
|
||||
void SetUp() override {}
|
||||
void TearDown() override {}
|
||||
|
||||
// Defines a PacketSequencerCalculator CalculatorGraphConfig::Node.
|
||||
CalculatorGraphConfig::Node BuildNodeConfig() {
|
||||
CalculatorGraphConfig::Node result;
|
||||
*result.mutable_calculator() = "PacketSequencerCalculator";
|
||||
*result.add_input_stream() = "INPUT:select";
|
||||
*result.add_input_stream() = "TICK:0:frame";
|
||||
*result.add_input_stream() = "TICK:1:mask";
|
||||
*result.add_output_stream() = "OUTPUT:select_timed";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// Shows the PacketSequencerCalculator is available.
|
||||
TEST_F(PacketSequencerCalculatorTest, IsRegistered) {
|
||||
EXPECT_TRUE(
|
||||
CalculatorBaseRegistry::IsRegistered("PacketSequencerCalculator"));
|
||||
}
|
||||
|
||||
// Shows how control packets recieve timestamps before and after frame packets
|
||||
// have arrived.
|
||||
TEST_F(PacketSequencerCalculatorTest, ChannelEarly) {
|
||||
CalculatorGraphConfig::Node node_config = BuildNodeConfig();
|
||||
CalculatorGraph graph = BuildCalculatorGraph(node_config);
|
||||
std::vector<Packet> outputs;
|
||||
MP_ASSERT_OK(graph.ObserveOutputStream("select_timed", [&](const Packet& p) {
|
||||
outputs.push_back(p);
|
||||
return absl::OkStatus();
|
||||
}));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
|
||||
// Some control packets arrive.
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("select", pack("p0_t10", 10)));
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("select", pack("p0_t20", 20)));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
// The control packets are assigned low timestamps.
|
||||
ASSERT_EQ(outputs.size(), 2);
|
||||
EXPECT_EQ(outputs[0].Get<std::string>(), "p0_t10");
|
||||
EXPECT_EQ(outputs[0].Timestamp(), Timestamp::Min());
|
||||
EXPECT_EQ(outputs[1].Timestamp(), Timestamp::Min() + 1);
|
||||
|
||||
// Some frame packets arrive.
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("mask", pack("p2_t10", 10)));
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("frame", pack("p1_t20", 20)));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
// Some more control packets arrive.
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("select", pack("p0_t30", 30)));
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream("select", pack("p0_t40", 40)));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
// New control packets are assigned timestamps following Timestamp(20).
|
||||
ASSERT_EQ(outputs.size(), 4);
|
||||
EXPECT_EQ(outputs[2].Get<std::string>(), "p0_t30");
|
||||
EXPECT_EQ(outputs[2].Timestamp(), Timestamp(21));
|
||||
EXPECT_EQ(outputs[3].Timestamp(), Timestamp(22));
|
||||
|
||||
MP_ASSERT_OK(graph.CloseAllPacketSources());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message PacketThinnerCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional PacketThinnerCalculatorOptions ext = 288533508;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message QuantizeFloatVectorCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional QuantizeFloatVectorCalculatorOptions ext = 259848061;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
message SequenceShiftCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional SequenceShiftCalculatorOptions ext = 107633927;
|
||||
|
||||
@@ -18,8 +18,6 @@ package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
option objc_class_prefix = "MediaPipe";
|
||||
|
||||
// A Range {begin, end} specifies beginning ane ending indices to splice a
|
||||
// vector. A vector v is spliced to have elements v[begin:(end-1)], i.e., with
|
||||
// begin index inclusive and end index exclusive.
|
||||
|
||||
Reference in New Issue
Block a user