Project import generated by Copybara.
PiperOrigin-RevId: 253489161
This commit is contained in:
@@ -0,0 +1,713 @@
|
||||
// Copyright 2019 The MediaPipe Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "mediapipe/framework/output_stream_manager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "mediapipe/framework/input_stream_handler.h"
|
||||
#include "mediapipe/framework/input_stream_manager.h"
|
||||
#include "mediapipe/framework/output_stream_shard.h"
|
||||
#include "mediapipe/framework/packet.h"
|
||||
#include "mediapipe/framework/port/gmock.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/framework/tool/tag_map_helper.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
namespace {
|
||||
|
||||
class OutputStreamManagerTest : public ::testing::Test {
|
||||
protected:
|
||||
OutputStreamManagerTest() {}
|
||||
|
||||
void SetUp() override {
|
||||
packet_type_.Set<std::string>();
|
||||
|
||||
headers_ready_callback_ =
|
||||
std::bind(&OutputStreamManagerTest::HeadersReadyNoOp, this);
|
||||
notification_callback_ =
|
||||
std::bind(&OutputStreamManagerTest::NotifyNoOp, this);
|
||||
schedule_callback_ = std::bind(&OutputStreamManagerTest::ScheduleNoOp, this,
|
||||
std::placeholders::_1);
|
||||
error_callback_ = std::bind(&OutputStreamManagerTest::RecordError, this,
|
||||
std::placeholders::_1);
|
||||
queue_full_callback_ =
|
||||
std::bind(&OutputStreamManagerTest::ReportQueueNoOp, this,
|
||||
std::placeholders::_1, std::placeholders::_2);
|
||||
queue_not_full_callback_ =
|
||||
std::bind(&OutputStreamManagerTest::ReportQueueNoOp, this,
|
||||
std::placeholders::_1, std::placeholders::_2);
|
||||
|
||||
output_stream_manager_ = absl::make_unique<OutputStreamManager>();
|
||||
MEDIAPIPE_ASSERT_OK(
|
||||
output_stream_manager_->Initialize("a_test", &packet_type_));
|
||||
output_stream_manager_->PrepareForRun(error_callback_);
|
||||
output_stream_shard_.SetSpec(output_stream_manager_->Spec());
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
|
||||
std::shared_ptr<tool::TagMap> tag_map = tool::CreateTagMap(1).ValueOrDie();
|
||||
mediapipe::StatusOr<std::unique_ptr<mediapipe::InputStreamHandler>>
|
||||
status_or_handler = InputStreamHandlerRegistry::CreateByName(
|
||||
"DefaultInputStreamHandler", tag_map, /*cc_manager=*/nullptr,
|
||||
MediaPipeOptions(), /*calculator_run_in_parallel=*/false);
|
||||
ASSERT_TRUE(status_or_handler.ok());
|
||||
input_stream_handler_ = std::move(status_or_handler.ValueOrDie());
|
||||
const CollectionItemId& id = tag_map->BeginId();
|
||||
|
||||
MEDIAPIPE_ASSERT_OK(input_stream_manager_.Initialize("a_test",
|
||||
&packet_type_,
|
||||
/*back_edge=*/false));
|
||||
MEDIAPIPE_ASSERT_OK(input_stream_handler_->InitializeInputStreamManagers(
|
||||
&input_stream_manager_));
|
||||
output_stream_manager_->AddMirror(input_stream_handler_.get(), id);
|
||||
input_stream_handler_->PrepareForRun(headers_ready_callback_,
|
||||
notification_callback_,
|
||||
schedule_callback_, error_callback_);
|
||||
input_stream_handler_->SetQueueSizeCallbacks(queue_full_callback_,
|
||||
queue_not_full_callback_);
|
||||
}
|
||||
|
||||
void HeadersReadyNoOp() {}
|
||||
|
||||
void NotifyNoOp() {}
|
||||
|
||||
void ScheduleNoOp(CalculatorContext* cc) {}
|
||||
|
||||
void RecordError(const ::mediapipe::Status& error) {
|
||||
errors_.push_back(error);
|
||||
}
|
||||
|
||||
void ReportQueueNoOp(InputStreamManager* stream, bool* stream_was_full) {}
|
||||
|
||||
// Returns the output_bound to verify.
|
||||
Timestamp ComputeBoundAndPropagateUpdates(Timestamp input_timestamp) {
|
||||
Timestamp output_bound =
|
||||
output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
return output_bound;
|
||||
}
|
||||
|
||||
PacketType packet_type_;
|
||||
|
||||
std::function<void()> headers_ready_callback_;
|
||||
std::function<void()> notification_callback_;
|
||||
std::function<void(CalculatorContext*)> schedule_callback_;
|
||||
std::function<void(::mediapipe::Status)> error_callback_;
|
||||
InputStreamManager::QueueSizeCallback queue_full_callback_;
|
||||
InputStreamManager::QueueSizeCallback queue_not_full_callback_;
|
||||
|
||||
std::unique_ptr<OutputStreamManager> output_stream_manager_;
|
||||
OutputStreamShard output_stream_shard_;
|
||||
std::unique_ptr<InputStreamHandler> input_stream_handler_;
|
||||
InputStreamManager input_stream_manager_;
|
||||
|
||||
// Vector of errors encountered while using the stream.
|
||||
std::vector<::mediapipe::Status> errors_;
|
||||
};
|
||||
|
||||
TEST_F(OutputStreamManagerTest, Init) {}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, ComputeOutputTimestampBoundWithoutOffset) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// If the offset isn't enabled, the input timestamp and the output bound are
|
||||
// not related. Since the output stream shard is empty, the output bound is
|
||||
// still equal to the previous timestamp bound of the stream.
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(10)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(11), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 2").At(Timestamp(20)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.SetNextTimestampBound(Timestamp(100));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the next timestamp bound.
|
||||
EXPECT_EQ(Timestamp(100), output_bound);
|
||||
|
||||
input_timestamp = Timestamp::Max();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// If the offset isn't enabled, the input timestamp and the output bound are
|
||||
// not related. The output bound is still based on the output stream shard.
|
||||
EXPECT_EQ(Timestamp(100), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, ComputeOutputTimestampBoundWithOffset) {
|
||||
output_stream_shard_.SetOffset(0);
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
// If the OutputStreamShard is empty, the output_bound is the next allowed
|
||||
// timestamp of the input_timestamp plus the offset.
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(1), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(10)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(11), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 2").At(Timestamp(20)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.SetNextTimestampBound(Timestamp(100));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the next timestamp bound.
|
||||
EXPECT_EQ(Timestamp(100), output_bound);
|
||||
|
||||
input_timestamp = Timestamp::Max();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the input timestamp, which is
|
||||
// Timestamp::Max().
|
||||
EXPECT_EQ(Timestamp::PostStream(), output_bound);
|
||||
|
||||
input_timestamp = Timestamp::PostStream();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the input timestamp, which is
|
||||
// Timestamp::PostStream().
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, ComputeOutputTimestampBoundWithNegativeOffset) {
|
||||
output_stream_shard_.SetOffset(-10);
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
// If the OutputStreamShard is empty, the output_bound is the next allowed
|
||||
// timestamp of the input_timestamp plus the negative offset.
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(-9), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(10)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(11), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 2").At(Timestamp(20)));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.SetNextTimestampBound(Timestamp(100));
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the next timestamp bound.
|
||||
EXPECT_EQ(Timestamp(100), output_bound);
|
||||
|
||||
input_timestamp = Timestamp::Max();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output bound is the next allowed timestamp of Timestamp::Max() plus the
|
||||
// negative offset.
|
||||
Timestamp expcted_bound(Timestamp::Max().Value() - 9);
|
||||
EXPECT_EQ(expcted_bound, output_bound);
|
||||
|
||||
input_timestamp = Timestamp::PostStream();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output_bound is based on the input timestamp, which is
|
||||
// Timestamp::PostStream(). Even with negative offset, it's expected that no
|
||||
// futher timestamps will occur.
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest,
|
||||
ComputeOutputTimestampBoundWithoutOffsetAfterOpenNode) {
|
||||
Timestamp input_timestamp = Timestamp::Unstarted();
|
||||
// If the OutputStreamShard is empty, the output_bound is
|
||||
// Timestamp::PreStream().
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::PreStream(), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(20)));
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.Close();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::Done(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest,
|
||||
ComputeOutputTimestampBoundWithOffsetAfterOpenNode) {
|
||||
output_stream_shard_.SetOffset(0);
|
||||
Timestamp input_timestamp = Timestamp::Unstarted();
|
||||
// If the OutputStreamShard is empty, the output_bound is always
|
||||
// Timestamp::PreStream() regardless of the offset.
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::PreStream(), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(20)));
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.Close();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::Done(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest,
|
||||
ComputeOutputTimestampBoundWithoutOffsetForPreStream) {
|
||||
Timestamp input_timestamp = Timestamp::PreStream();
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
// If the OutputStreamShard is empty, the output bound is equal to the
|
||||
// previous timestamp bound of the stream.
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(20)));
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.Close();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::Done(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest,
|
||||
ComputeOutputTimestampBoundWithOffsetForPreStream) {
|
||||
output_stream_shard_.SetOffset(0);
|
||||
Timestamp input_timestamp = Timestamp::PreStream();
|
||||
// If the OutputStreamShard is empty, the output_bound is always
|
||||
// Timestamp::Min() regardless of the offset.
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::Min(), output_bound);
|
||||
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("Packet 1").At(Timestamp(20)));
|
||||
// The output_bound is based on the timestamp of the last added packet.
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(21), output_bound);
|
||||
|
||||
output_stream_shard_.Close();
|
||||
output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::Done(), output_bound);
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacket) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp(10)));
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp(20)));
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 3").At(Timestamp(30)));
|
||||
EXPECT_FALSE(output_stream_shard_.IsEmpty());
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
|
||||
EXPECT_EQ(Timestamp(31), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(output_stream_shard_.IsEmpty());
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
// The stream should reject the four timestamps that are not allowed in a
|
||||
// stream: Timestamp::Unset(), Timestamp::Unstarted(),
|
||||
// Timestamp::OneOverPostStream(), and Timestamp::Done().
|
||||
TEST_F(OutputStreamManagerTest, AddPacketUnset) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::Unset()));
|
||||
// This error is reported by OutputStreamShard rather than InputStreamManager.
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_TRUE(output_stream_shard_.IsEmpty());
|
||||
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output bound is still equal to the previous timestamp bound of the
|
||||
// stream.
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(), testing::HasSubstr("Timestamp::Unset()"));
|
||||
// Nothing changed in the input stream.
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketUnstarted) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::Unstarted()));
|
||||
// This error is reported by OutputStreamShard rather than InputStreamManager.
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_TRUE(output_stream_shard_.IsEmpty());
|
||||
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output bound is still equal to the previous timestamp bound of the
|
||||
// stream.
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(),
|
||||
testing::HasSubstr("Timestamp::Unstarted()"));
|
||||
// Nothing changed in the input stream.
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketOneOverPostStream) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::OneOverPostStream()));
|
||||
// This error is reported by OutputStreamShard rather than InputStreamManager.
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_TRUE(output_stream_shard_.IsEmpty());
|
||||
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output bound is still equal to the previous timestamp bound of the
|
||||
// stream.
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(),
|
||||
testing::HasSubstr("Timestamp::OneOverPostStream()"));
|
||||
// Nothing changed in the input stream.
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketdDone) {
|
||||
Timestamp input_timestamp = Timestamp(0);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::Done()));
|
||||
// This error is reported by OutputStreamShard rather than InputStreamManager.
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_TRUE(output_stream_shard_.IsEmpty());
|
||||
|
||||
Timestamp stream_previous_timestamp_bound =
|
||||
output_stream_manager_->NextTimestampBound();
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// The output bound is still equal to the previous timestamp bound of the
|
||||
// stream.
|
||||
EXPECT_EQ(stream_previous_timestamp_bound, output_bound);
|
||||
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(), testing::HasSubstr("Timestamp::Done()"));
|
||||
// Nothing changed in the input stream.
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketOnlyPreStream) {
|
||||
Timestamp input_timestamp = Timestamp::PreStream();
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::PreStream()));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(),
|
||||
ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
// An attempt to add a packet after Timestamp::PreStream() should be rejected
|
||||
// because the next timestamp bound is Timestamp::OneOverPostStream().
|
||||
TEST_F(OutputStreamManagerTest, AddPacketAfterPreStream) {
|
||||
Timestamp input_timestamp = Timestamp::PreStream();
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::PreStream()));
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(),
|
||||
ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(10);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp(10)));
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(11), output_bound);
|
||||
// This error is reported by InputStreamManager rather than
|
||||
// OutputStreamManager.
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(),
|
||||
testing::HasSubstr("Timestamp::OneOverPostStream()"));
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketOnlyPostStream) {
|
||||
Timestamp input_timestamp = Timestamp::PostStream();
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::PostStream()));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(),
|
||||
ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
// A packet at Timestamp::PostStream() must be the only Packet in a stream.
|
||||
TEST_F(OutputStreamManagerTest, AddPacketBeforePostStream) {
|
||||
Timestamp input_timestamp = Timestamp(10);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp(10)));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_EQ(Timestamp(11), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(20);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp::PostStream()));
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(), output_bound);
|
||||
// This error is reported by InputStreamManager rather than
|
||||
// OutputStreamManager.
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(),
|
||||
testing::HasSubstr("Timestamp::PostStream()"));
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketReverseTimestamps) {
|
||||
Timestamp input_timestamp = Timestamp(20);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp(20)));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_EQ(Timestamp(21), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(10);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp(10)));
|
||||
Timestamp output_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
EXPECT_EQ(Timestamp(11), output_bound);
|
||||
// This error is reported by InputStreamManager rather than
|
||||
// OutputStreamManager.
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(output_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_FALSE(errors_[0].ok());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, SetNextTimestampBoundReverseTimestamps) {
|
||||
Timestamp input_timestamp = Timestamp(20);
|
||||
output_stream_shard_.SetNextTimestampBound(Timestamp(50));
|
||||
EXPECT_EQ(Timestamp(50), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.SetNextTimestampBound(
|
||||
Timestamp(40)); // Set Timestamp bound backwards in time.
|
||||
Timestamp next_bound = output_stream_manager_->ComputeOutputTimestampBound(
|
||||
output_stream_shard_, input_timestamp);
|
||||
// This error is reported by InputStreamManager rather than
|
||||
// OutputStreamManager.
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
output_stream_manager_->PropagateUpdatesToMirrors(next_bound,
|
||||
&output_stream_shard_);
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_THAT(errors_[0].ToString(), testing::HasSubstr("50"));
|
||||
EXPECT_THAT(errors_[0].ToString(), testing::HasSubstr("40"));
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, BadPacketType) {
|
||||
output_stream_shard_.AddPacket(Adopt(new int(10)).At(Timestamp(10)));
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_FALSE(errors_[0].ok());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, SetHeader) {
|
||||
Packet header = MakePacket<std::string>("header");
|
||||
output_stream_shard_.SetHeader(header);
|
||||
output_stream_manager_->PropagateHeader();
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
EXPECT_EQ(header.Get<std::string>(),
|
||||
output_stream_manager_->Header().Get<std::string>());
|
||||
EXPECT_EQ(header.Timestamp(), output_stream_manager_->Header().Timestamp());
|
||||
EXPECT_EQ(header.Get<std::string>(),
|
||||
input_stream_manager_.Header().Get<std::string>());
|
||||
EXPECT_EQ(header.Timestamp(), input_stream_manager_.Header().Timestamp());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, SetHeaderWithTimestamp) {
|
||||
Packet header = MakePacket<std::string>("header").At(Timestamp(10));
|
||||
output_stream_shard_.SetHeader(header);
|
||||
output_stream_manager_->PropagateHeader();
|
||||
ASSERT_EQ(1, errors_.size());
|
||||
EXPECT_FALSE(errors_[0].ok());
|
||||
}
|
||||
|
||||
// An attempt to add a packet after Timestamp::PreStream() should be allowed
|
||||
// if packet timestamps don't need to be increasing.
|
||||
TEST_F(OutputStreamManagerTest, AddPacketAfterPreStreamUntimed) {
|
||||
input_stream_manager_.DisableTimestamps();
|
||||
Timestamp input_timestamp = Timestamp::PreStream();
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp::PreStream()));
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(),
|
||||
ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(10);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp(10)));
|
||||
EXPECT_EQ(Timestamp(11), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
// A packet at Timestamp::PostStream() does not need to be the only Packet in
|
||||
// a stream if packet timestamps don't need to be increasing.
|
||||
TEST_F(OutputStreamManagerTest, AddPacketBeforePostStreamUntimed) {
|
||||
input_stream_manager_.DisableTimestamps();
|
||||
Timestamp input_timestamp = Timestamp(10);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp(10)));
|
||||
EXPECT_EQ(Timestamp(11), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp::PostStream();
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp::PostStream()));
|
||||
EXPECT_EQ(Timestamp::OneOverPostStream(),
|
||||
ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketReverseTimestampsUntimed) {
|
||||
input_stream_manager_.DisableTimestamps();
|
||||
Timestamp input_timestamp = Timestamp(20);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 1").At(Timestamp(20)));
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_EQ(Timestamp(21), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(10);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.AddPacket(
|
||||
MakePacket<std::string>("packet 2").At(Timestamp(10)));
|
||||
EXPECT_EQ(Timestamp(11), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, SetNextTimestampBoundReverseTimestampsUntimed) {
|
||||
input_stream_manager_.DisableTimestamps();
|
||||
Timestamp input_timestamp = Timestamp(20);
|
||||
output_stream_shard_.SetNextTimestampBound(Timestamp(50));
|
||||
EXPECT_EQ(Timestamp(50), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
|
||||
input_timestamp = Timestamp(30);
|
||||
output_stream_manager_->ResetShard(&output_stream_shard_);
|
||||
output_stream_shard_.SetNextTimestampBound(
|
||||
Timestamp(40)); // Set Timestamp bound backwards in time.
|
||||
EXPECT_EQ(Timestamp(40), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
TEST_F(OutputStreamManagerTest, AddPacketAndMovePacket) {
|
||||
Timestamp input_timestamp = Timestamp(10);
|
||||
Packet packet_1 = MakePacket<std::string>("packet 1").At(Timestamp(10));
|
||||
output_stream_shard_.AddPacket(packet_1);
|
||||
// packet_1 has an extra copy in the output stream.
|
||||
ASSERT_FALSE(packet_1.IsEmpty());
|
||||
MEDIAPIPE_ASSERT_OK(packet_1.ValidateAsType<std::string>());
|
||||
EXPECT_EQ("packet 1", packet_1.Get<std::string>());
|
||||
|
||||
Packet packet_2 = MakePacket<std::string>("packet 2").At(Timestamp(20));
|
||||
output_stream_shard_.AddPacket(std::move(packet_2));
|
||||
// packet_2 is moved into the output stream.
|
||||
ASSERT_TRUE(packet_2.IsEmpty()); // NOLINT used after std::move().
|
||||
|
||||
EXPECT_TRUE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_EQ(Timestamp(21), ComputeBoundAndPropagateUpdates(input_timestamp));
|
||||
EXPECT_FALSE(input_stream_manager_.IsEmpty());
|
||||
EXPECT_TRUE(errors_.empty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
||||
Reference in New Issue
Block a user