blob: 5f225ef3c7b09505c6bba9e4092f5e4359fcdcd8 [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 <gtest/gtest.h>
#include <stdint.h>
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "media/cast/constants.h"
#include "media/cast/net/rtp/rtp_defines.h"
#include "media/cast/test/receiver/receiver_stats.h"
namespace media {
namespace cast {
static const int64_t kStartMillisecond = INT64_C(12345678900000);
static const uint32_t kStdTimeIncrementMs = 33;
class ReceiverStatsTest : public ::testing::Test {
protected:
ReceiverStatsTest() : stats_(&testing_clock_) {
testing_clock_.Advance(base::Milliseconds(kStartMillisecond));
start_time_ = testing_clock_.NowTicks();
delta_increments_ = base::Milliseconds(kStdTimeIncrementMs);
}
~ReceiverStatsTest() override = default;
uint32_t ExpectedJitter(uint32_t const_interval, int num_packets) {
float jitter = 0;
// Assume timestamps have a constant kStdTimeIncrementMs interval.
float float_interval =
static_cast<float>(const_interval - kStdTimeIncrementMs);
for (int i = 0; i < num_packets; ++i) {
jitter += (float_interval - jitter) / 16;
}
return static_cast<uint32_t>(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_, kVideoFrequency);
if (i % 3) {
rtp_header_.rtp_timestamp +=
RtpTimeDelta::FromTimeDelta(base::Milliseconds(33), kVideoFrequency);
}
++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_t 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_, kVideoFrequency);
if (i % 3) {
rtp_header_.rtp_timestamp +=
RtpTimeDelta::FromTimeDelta(base::Milliseconds(33), kVideoFrequency);
}
++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_t 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_t kStartSequenceNumber = 65500;
rtp_header_.sequence_number = kStartSequenceNumber;
for (int i = 0; i < 300; ++i) {
if (i % 4)
stats_.UpdateStatistics(rtp_header_, kVideoFrequency);
if (i % 3)
rtp_header_.rtp_timestamp += RtpTimeDelta::FromTicks(1);
++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_t 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_, kVideoFrequency);
++rtp_header_.sequence_number;
rtp_header_.rtp_timestamp +=
RtpTimeDelta::FromTimeDelta(base::Milliseconds(33), kVideoFrequency);
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_t 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_, kVideoFrequency);
++rtp_header_.sequence_number;
rtp_header_.rtp_timestamp +=
RtpTimeDelta::FromTimeDelta(base::Milliseconds(33), kVideoFrequency);
base::TimeDelta additional_delta = base::Milliseconds(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_t 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