blob: 13f32c3fe8350e66d11789d69649b0047e5b1d12 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/cast/logging/receiver_time_offset_estimator_impl.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/memory/ref_counted.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/tick_clock.h"
#include "media/base/fake_single_thread_task_runner.h"
#include "media/cast/cast_environment.h"
#include "media/cast/logging/logging_defines.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
namespace cast {
class ReceiverTimeOffsetEstimatorImplTest : public ::testing::Test {
protected:
ReceiverTimeOffsetEstimatorImplTest()
: sender_clock_(new base::SimpleTestTickClock()),
task_runner_(new FakeSingleThreadTaskRunner(sender_clock_)),
cast_environment_(
new CastEnvironment(std::unique_ptr<base::TickClock>(sender_clock_),
task_runner_,
task_runner_,
task_runner_)) {
cast_environment_->logger()->Subscribe(&estimator_);
}
~ReceiverTimeOffsetEstimatorImplTest() override {
cast_environment_->logger()->Unsubscribe(&estimator_);
}
void AdvanceClocks(base::TimeDelta time) {
task_runner_->Sleep(time);
receiver_clock_.Advance(time);
}
base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment.
scoped_refptr<FakeSingleThreadTaskRunner> task_runner_;
scoped_refptr<CastEnvironment> cast_environment_;
base::SimpleTestTickClock receiver_clock_;
ReceiverTimeOffsetEstimatorImpl estimator_;
};
// Suppose the true offset is 100ms.
// Event A occurred at sender time 20ms.
// Event B occurred at receiver time 130ms. (sender time 30ms)
// Event C occurred at sender time 60ms.
// Then the bound after all 3 events have arrived is [130-60=70, 130-20=110].
TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) {
int64_t true_offset_ms = 100;
receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
base::TimeDelta lower_bound;
base::TimeDelta upper_bound;
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
const RtpTimeTicks rtp_timestamp;
FrameId frame_id = FrameId::first();
AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
std::unique_ptr<FrameEvent> encode_event(new FrameEvent());
encode_event->timestamp = sender_clock_->NowTicks();
encode_event->type = FRAME_ENCODED;
encode_event->media_type = VIDEO_EVENT;
encode_event->rtp_timestamp = rtp_timestamp;
encode_event->frame_id = frame_id;
encode_event->size = 1234;
encode_event->key_frame = true;
encode_event->target_bitrate = 5678;
encode_event->encoder_cpu_utilization = 9.10;
encode_event->idealized_bitrate_utilization = 11.12;
cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
std::unique_ptr<PacketEvent> send_event(new PacketEvent());
send_event->timestamp = sender_clock_->NowTicks();
send_event->type = PACKET_SENT_TO_NETWORK;
send_event->media_type = VIDEO_EVENT;
send_event->rtp_timestamp = rtp_timestamp;
send_event->frame_id = frame_id;
send_event->packet_id = 56;
send_event->max_packet_id = 78;
send_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(send_event));
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
std::unique_ptr<FrameEvent> ack_sent_event(new FrameEvent());
ack_sent_event->timestamp = receiver_clock_.NowTicks();
ack_sent_event->type = FRAME_ACK_SENT;
ack_sent_event->media_type = VIDEO_EVENT;
ack_sent_event->rtp_timestamp = rtp_timestamp;
ack_sent_event->frame_id = frame_id;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_sent_event));
std::unique_ptr<PacketEvent> receive_event(new PacketEvent());
receive_event->timestamp = receiver_clock_.NowTicks();
receive_event->type = PACKET_RECEIVED;
receive_event->media_type = VIDEO_EVENT;
receive_event->rtp_timestamp = rtp_timestamp;
receive_event->frame_id = frame_id;
receive_event->packet_id = 56;
receive_event->max_packet_id = 78;
receive_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(receive_event));
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
std::unique_ptr<FrameEvent> ack_event(new FrameEvent());
ack_event->timestamp = sender_clock_->NowTicks();
ack_event->type = FRAME_ACK_RECEIVED;
ack_event->media_type = VIDEO_EVENT;
ack_event->rtp_timestamp = rtp_timestamp;
ack_event->frame_id = frame_id;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
int64_t lower_bound_ms = lower_bound.InMilliseconds();
int64_t upper_bound_ms = upper_bound.InMilliseconds();
EXPECT_EQ(70, lower_bound_ms);
EXPECT_EQ(110, upper_bound_ms);
EXPECT_GE(true_offset_ms, lower_bound_ms);
EXPECT_LE(true_offset_ms, upper_bound_ms);
}
// Same scenario as above, but event C arrives before event B. It doesn't mean
// event C occurred before event B.
TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) {
int64_t true_offset_ms = 100;
receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
base::TimeDelta lower_bound;
base::TimeDelta upper_bound;
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
const RtpTimeTicks rtp_timestamp;
FrameId frame_id = FrameId::first();
AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
std::unique_ptr<FrameEvent> encode_event(new FrameEvent());
encode_event->timestamp = sender_clock_->NowTicks();
encode_event->type = FRAME_ENCODED;
encode_event->media_type = VIDEO_EVENT;
encode_event->rtp_timestamp = rtp_timestamp;
encode_event->frame_id = frame_id;
encode_event->size = 1234;
encode_event->key_frame = true;
encode_event->target_bitrate = 5678;
encode_event->encoder_cpu_utilization = 9.10;
encode_event->idealized_bitrate_utilization = 11.12;
cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
std::unique_ptr<PacketEvent> send_event(new PacketEvent());
send_event->timestamp = sender_clock_->NowTicks();
send_event->type = PACKET_SENT_TO_NETWORK;
send_event->media_type = VIDEO_EVENT;
send_event->rtp_timestamp = rtp_timestamp;
send_event->frame_id = frame_id;
send_event->packet_id = 56;
send_event->max_packet_id = 78;
send_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(send_event));
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
base::TimeTicks event_b_time = receiver_clock_.NowTicks();
AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
base::TimeTicks event_c_time = sender_clock_->NowTicks();
std::unique_ptr<FrameEvent> ack_event(new FrameEvent());
ack_event->timestamp = event_c_time;
ack_event->type = FRAME_ACK_RECEIVED;
ack_event->media_type = VIDEO_EVENT;
ack_event->rtp_timestamp = rtp_timestamp;
ack_event->frame_id = frame_id;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
std::unique_ptr<PacketEvent> receive_event(new PacketEvent());
receive_event->timestamp = event_b_time;
receive_event->type = PACKET_RECEIVED;
receive_event->media_type = VIDEO_EVENT;
receive_event->rtp_timestamp = rtp_timestamp;
receive_event->frame_id = frame_id;
receive_event->packet_id = 56;
receive_event->max_packet_id = 78;
receive_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(receive_event));
std::unique_ptr<FrameEvent> ack_sent_event(new FrameEvent());
ack_sent_event->timestamp = event_b_time;
ack_sent_event->type = FRAME_ACK_SENT;
ack_sent_event->media_type = VIDEO_EVENT;
ack_sent_event->rtp_timestamp = rtp_timestamp;
ack_sent_event->frame_id = frame_id;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_sent_event));
EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
int64_t lower_bound_ms = lower_bound.InMilliseconds();
int64_t upper_bound_ms = upper_bound.InMilliseconds();
EXPECT_EQ(70, lower_bound_ms);
EXPECT_EQ(110, upper_bound_ms);
EXPECT_GE(true_offset_ms, lower_bound_ms);
EXPECT_LE(true_offset_ms, upper_bound_ms);
}
TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
int64_t true_offset_ms = 100;
receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
base::TimeDelta lower_bound;
base::TimeDelta upper_bound;
const RtpTimeTicks rtp_timestamp_a;
FrameId frame_id_a = FrameId::first();
const RtpTimeTicks rtp_timestamp_b =
rtp_timestamp_a + RtpTimeDelta::FromTicks(90);
FrameId frame_id_b = frame_id_a + 1;
const RtpTimeTicks rtp_timestamp_c =
rtp_timestamp_b + RtpTimeDelta::FromTicks(90);
FrameId frame_id_c = frame_id_b + 1;
// Frame 1 times: [20, 30+100, 60]
// Frame 2 times: [30, 50+100, 55]
// Frame 3 times: [77, 80+100, 110]
// Bound should end up at [95, 103]
// Events times in chronological order: 20, 30 x2, 50, 55, 60, 77, 80, 110
AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
std::unique_ptr<FrameEvent> encode_event(new FrameEvent());
encode_event->timestamp = sender_clock_->NowTicks();
encode_event->type = FRAME_ENCODED;
encode_event->media_type = VIDEO_EVENT;
encode_event->rtp_timestamp = rtp_timestamp_a;
encode_event->frame_id = frame_id_a;
encode_event->size = 1234;
encode_event->key_frame = true;
encode_event->target_bitrate = 5678;
encode_event->encoder_cpu_utilization = 9.10;
encode_event->idealized_bitrate_utilization = 11.12;
cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
std::unique_ptr<PacketEvent> send_event(new PacketEvent());
send_event->timestamp = sender_clock_->NowTicks();
send_event->type = PACKET_SENT_TO_NETWORK;
send_event->media_type = VIDEO_EVENT;
send_event->rtp_timestamp = rtp_timestamp_a;
send_event->frame_id = frame_id_a;
send_event->packet_id = 56;
send_event->max_packet_id = 78;
send_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(send_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
encode_event.reset(new FrameEvent());
encode_event->timestamp = sender_clock_->NowTicks();
encode_event->type = FRAME_ENCODED;
encode_event->media_type = VIDEO_EVENT;
encode_event->rtp_timestamp = rtp_timestamp_b;
encode_event->frame_id = frame_id_b;
encode_event->size = 1234;
encode_event->key_frame = true;
encode_event->target_bitrate = 5678;
encode_event->encoder_cpu_utilization = 9.10;
encode_event->idealized_bitrate_utilization = 11.12;
cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
send_event.reset(new PacketEvent());
send_event->timestamp = sender_clock_->NowTicks();
send_event->type = PACKET_SENT_TO_NETWORK;
send_event->media_type = VIDEO_EVENT;
send_event->rtp_timestamp = rtp_timestamp_b;
send_event->frame_id = frame_id_b;
send_event->packet_id = 56;
send_event->max_packet_id = 78;
send_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(send_event));
std::unique_ptr<FrameEvent> ack_sent_event(new FrameEvent());
ack_sent_event->timestamp = receiver_clock_.NowTicks();
ack_sent_event->type = FRAME_ACK_SENT;
ack_sent_event->media_type = VIDEO_EVENT;
ack_sent_event->rtp_timestamp = rtp_timestamp_a;
ack_sent_event->frame_id = frame_id_a;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_sent_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
std::unique_ptr<PacketEvent> receive_event(new PacketEvent());
receive_event->timestamp = receiver_clock_.NowTicks();
receive_event->type = PACKET_RECEIVED;
receive_event->media_type = VIDEO_EVENT;
receive_event->rtp_timestamp = rtp_timestamp_b;
receive_event->frame_id = frame_id_b;
receive_event->packet_id = 56;
receive_event->max_packet_id = 78;
receive_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(receive_event));
ack_sent_event.reset(new FrameEvent());
ack_sent_event->timestamp = receiver_clock_.NowTicks();
ack_sent_event->type = FRAME_ACK_SENT;
ack_sent_event->media_type = VIDEO_EVENT;
ack_sent_event->rtp_timestamp = rtp_timestamp_b;
ack_sent_event->frame_id = frame_id_b;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_sent_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(5));
std::unique_ptr<FrameEvent> ack_event(new FrameEvent());
ack_event->timestamp = sender_clock_->NowTicks();
ack_event->type = FRAME_ACK_RECEIVED;
ack_event->media_type = VIDEO_EVENT;
ack_event->rtp_timestamp = rtp_timestamp_b;
ack_event->frame_id = frame_id_b;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(5));
ack_event.reset(new FrameEvent());
ack_event->timestamp = sender_clock_->NowTicks();
ack_event->type = FRAME_ACK_RECEIVED;
ack_event->media_type = VIDEO_EVENT;
ack_event->rtp_timestamp = rtp_timestamp_a;
ack_event->frame_id = frame_id_a;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(17));
encode_event.reset(new FrameEvent());
encode_event->timestamp = sender_clock_->NowTicks();
encode_event->type = FRAME_ENCODED;
encode_event->media_type = VIDEO_EVENT;
encode_event->rtp_timestamp = rtp_timestamp_c;
encode_event->frame_id = frame_id_c;
encode_event->size = 1234;
encode_event->key_frame = true;
encode_event->target_bitrate = 5678;
encode_event->encoder_cpu_utilization = 9.10;
encode_event->idealized_bitrate_utilization = 11.12;
cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
send_event.reset(new PacketEvent());
send_event->timestamp = sender_clock_->NowTicks();
send_event->type = PACKET_SENT_TO_NETWORK;
send_event->media_type = VIDEO_EVENT;
send_event->rtp_timestamp = rtp_timestamp_c;
send_event->frame_id = frame_id_c;
send_event->packet_id = 56;
send_event->max_packet_id = 78;
send_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(send_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(3));
receive_event.reset(new PacketEvent());
receive_event->timestamp = receiver_clock_.NowTicks();
receive_event->type = PACKET_RECEIVED;
receive_event->media_type = VIDEO_EVENT;
receive_event->rtp_timestamp = rtp_timestamp_c;
receive_event->frame_id = frame_id_c;
receive_event->packet_id = 56;
receive_event->max_packet_id = 78;
receive_event->size = 1500;
cast_environment_->logger()->DispatchPacketEvent(std::move(receive_event));
ack_sent_event.reset(new FrameEvent());
ack_sent_event->timestamp = receiver_clock_.NowTicks();
ack_sent_event->type = FRAME_ACK_SENT;
ack_sent_event->media_type = VIDEO_EVENT;
ack_sent_event->rtp_timestamp = rtp_timestamp_c;
ack_sent_event->frame_id = frame_id_c;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_sent_event));
AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
ack_event.reset(new FrameEvent());
ack_event->timestamp = sender_clock_->NowTicks();
ack_event->type = FRAME_ACK_RECEIVED;
ack_event->media_type = VIDEO_EVENT;
ack_event->rtp_timestamp = rtp_timestamp_c;
ack_event->frame_id = frame_id_c;
cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
int64_t lower_bound_ms = lower_bound.InMilliseconds();
int64_t upper_bound_ms = upper_bound.InMilliseconds();
EXPECT_GT(lower_bound_ms, 90);
EXPECT_LE(lower_bound_ms, true_offset_ms);
EXPECT_LT(upper_bound_ms, 150);
EXPECT_GT(upper_bound_ms, true_offset_ms);
}
} // namespace cast
} // namespace media