// 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 #include #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" #include "media/cast/net/rtp/receiver_stats.h" #include "media/cast/net/rtp/rtp_defines.h" namespace media { namespace cast { static const int64 kStartMillisecond = INT64_C(12345678900000); static const uint32 kStdTimeIncrementMs = 33; class ReceiverStatsTest : public ::testing::Test { protected: ReceiverStatsTest() : stats_(&testing_clock_) { testing_clock_.Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); start_time_ = testing_clock_.NowTicks(); delta_increments_ = base::TimeDelta::FromMilliseconds(kStdTimeIncrementMs); } ~ReceiverStatsTest() override {} uint32 ExpectedJitter(uint32 const_interval, int num_packets) { float jitter = 0; // Assume timestamps have a constant kStdTimeIncrementMs interval. float float_interval = static_cast(const_interval - kStdTimeIncrementMs); for (int i = 0; i < num_packets; ++i) { jitter += (float_interval - jitter) / 16; } return static_cast(jitter + 0.5f); } ReceiverStats stats_; RtpCastHeader rtp_header_; base::SimpleTestTickClock testing_clock_; base::TimeTicks start_time_; base::TimeDelta delta_increments_; private: DISALLOW_COPY_AND_ASSIGN(ReceiverStatsTest); }; TEST_F(ReceiverStatsTest, ResetState) { RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_EQ(0u, s.fraction_lost); EXPECT_EQ(0u, s.cumulative_lost); EXPECT_EQ(0u, s.extended_high_sequence_number); EXPECT_EQ(0u, s.jitter); } TEST_F(ReceiverStatsTest, LossCount) { for (int i = 0; i < 300; ++i) { if (i % 4) stats_.UpdateStatistics(rtp_header_); if (i % 3) { rtp_header_.rtp_timestamp += 33 * 90; } ++rtp_header_.sequence_number; testing_clock_.Advance(delta_increments_); } RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_EQ(63u, s.fraction_lost); EXPECT_EQ(74u, s.cumulative_lost); // Build extended sequence number. const uint32 extended_seq_num = rtp_header_.sequence_number - 1; EXPECT_EQ(extended_seq_num, s.extended_high_sequence_number); } TEST_F(ReceiverStatsTest, NoLossWrap) { rtp_header_.sequence_number = 65500; for (int i = 0; i < 300; ++i) { stats_.UpdateStatistics(rtp_header_); if (i % 3) { rtp_header_.rtp_timestamp += 33 * 90; } ++rtp_header_.sequence_number; testing_clock_.Advance(delta_increments_); } RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_EQ(0u, s.fraction_lost); EXPECT_EQ(0u, s.cumulative_lost); // Build extended sequence number (one wrap cycle). const uint32 extended_seq_num = (1 << 16) + rtp_header_.sequence_number - 1; EXPECT_EQ(extended_seq_num, s.extended_high_sequence_number); } TEST_F(ReceiverStatsTest, LossCountWrap) { const uint32 kStartSequenceNumber = 65500; rtp_header_.sequence_number = kStartSequenceNumber; for (int i = 0; i < 300; ++i) { if (i % 4) stats_.UpdateStatistics(rtp_header_); if (i % 3) // Update timestamp. ++rtp_header_.rtp_timestamp; ++rtp_header_.sequence_number; testing_clock_.Advance(delta_increments_); } RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_EQ(63u, s.fraction_lost); EXPECT_EQ(74u, s.cumulative_lost); // Build extended sequence number (one wrap cycle). const uint32 extended_seq_num = (1 << 16) + rtp_header_.sequence_number - 1; EXPECT_EQ(extended_seq_num, s.extended_high_sequence_number); } TEST_F(ReceiverStatsTest, BasicJitter) { for (int i = 0; i < 300; ++i) { stats_.UpdateStatistics(rtp_header_); ++rtp_header_.sequence_number; rtp_header_.rtp_timestamp += 33 * 90; testing_clock_.Advance(delta_increments_); } RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_FALSE(s.fraction_lost); EXPECT_FALSE(s.cumulative_lost); // Build extended sequence number (one wrap cycle). const uint32 extended_seq_num = rtp_header_.sequence_number - 1; EXPECT_EQ(extended_seq_num, s.extended_high_sequence_number); EXPECT_EQ(ExpectedJitter(kStdTimeIncrementMs, 300), s.jitter); } TEST_F(ReceiverStatsTest, NonTrivialJitter) { const int kAdditionalIncrement = 5; for (int i = 0; i < 300; ++i) { stats_.UpdateStatistics(rtp_header_); ++rtp_header_.sequence_number; rtp_header_.rtp_timestamp += 33 * 90; base::TimeDelta additional_delta = base::TimeDelta::FromMilliseconds(kAdditionalIncrement); testing_clock_.Advance(delta_increments_ + additional_delta); } RtpReceiverStatistics s = stats_.GetStatistics(); EXPECT_FALSE(s.fraction_lost); EXPECT_FALSE(s.cumulative_lost); // Build extended sequence number (one wrap cycle). const uint32 extended_seq_num = rtp_header_.sequence_number - 1; EXPECT_EQ(extended_seq_num, s.extended_high_sequence_number); EXPECT_EQ(ExpectedJitter(kStdTimeIncrementMs + kAdditionalIncrement, 300), s.jitter); } } // namespace cast } // namespace media