webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
Erik Språng 788ac70c1f Don't overwrite RTP packets in history within one second or 3x RTT.
This prevents us from prematurely overwriting the packets in the history
if the RTT is underestimated.

Bug: webrtc:8766
Change-Id: I042e8ce74cdce2a0451596f4217779fc856b51f4
Reviewed-on: https://webrtc-review.googlesource.com/42960
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21735}
2018-01-23 17:08:28 +00:00

295 lines
11 KiB
C++

/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/rtp_packet_history.h"
#include <memory>
#include <utility>
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "system_wrappers/include/clock.h"
#include "test/gtest.h"
#include "typedefs.h" // NOLINT(build/include)
namespace webrtc {
class RtpPacketHistoryTest : public ::testing::Test {
protected:
static constexpr uint16_t kSeqNum = 88;
RtpPacketHistoryTest() : fake_clock_(123456), hist_(&fake_clock_) {}
SimulatedClock fake_clock_;
RtpPacketHistory hist_;
std::unique_ptr<RtpPacketToSend> CreateRtpPacket(uint16_t seq_num) {
// Payload, ssrc, timestamp and extensions are irrelevant for this tests.
std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(nullptr));
packet->SetSequenceNumber(seq_num);
packet->set_capture_time_ms(fake_clock_.TimeInMilliseconds());
return packet;
}
};
TEST_F(RtpPacketHistoryTest, SetStoreStatus) {
EXPECT_FALSE(hist_.StorePackets());
hist_.SetStorePacketsStatus(true, 10);
EXPECT_TRUE(hist_.StorePackets());
hist_.SetStorePacketsStatus(false, 0);
EXPECT_FALSE(hist_.StorePackets());
}
TEST_F(RtpPacketHistoryTest, NoStoreStatus) {
EXPECT_FALSE(hist_.StorePackets());
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
// Packet should not be stored.
EXPECT_FALSE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false));
}
TEST_F(RtpPacketHistoryTest, GetRtpPacket_NotStored) {
hist_.SetStorePacketsStatus(true, 10);
EXPECT_FALSE(hist_.GetPacketAndSetSendTime(0, 0, false));
}
TEST_F(RtpPacketHistoryTest, PutRtpPacket) {
hist_.SetStorePacketsStatus(true, 10);
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
EXPECT_FALSE(hist_.HasRtpPacket(kSeqNum));
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum));
}
TEST_F(RtpPacketHistoryTest, GetRtpPacket) {
hist_.SetStorePacketsStatus(true, 10);
int64_t capture_time_ms = 1;
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
packet->set_capture_time_ms(capture_time_ms);
rtc::CopyOnWriteBuffer buffer = packet->Buffer();
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
std::unique_ptr<RtpPacketToSend> packet_out =
hist_.GetPacketAndSetSendTime(kSeqNum, 0, false);
EXPECT_TRUE(packet_out);
EXPECT_EQ(buffer, packet_out->Buffer());
EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms());
}
TEST_F(RtpPacketHistoryTest, NoCaptureTime) {
hist_.SetStorePacketsStatus(true, 10);
fake_clock_.AdvanceTimeMilliseconds(1);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
packet->set_capture_time_ms(-1);
rtc::CopyOnWriteBuffer buffer = packet->Buffer();
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
std::unique_ptr<RtpPacketToSend> packet_out =
hist_.GetPacketAndSetSendTime(kSeqNum, 0, false);
EXPECT_TRUE(packet_out);
EXPECT_EQ(buffer, packet_out->Buffer());
EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms());
}
TEST_F(RtpPacketHistoryTest, DontRetransmit) {
hist_.SetStorePacketsStatus(true, 10);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
rtc::CopyOnWriteBuffer buffer = packet->Buffer();
hist_.PutRtpPacket(std::move(packet), kDontRetransmit, false);
std::unique_ptr<RtpPacketToSend> packet_out;
packet_out = hist_.GetPacketAndSetSendTime(kSeqNum, 0, true);
EXPECT_FALSE(packet_out);
packet_out = hist_.GetPacketAndSetSendTime(kSeqNum, 0, false);
EXPECT_TRUE(packet_out);
EXPECT_EQ(buffer.size(), packet_out->size());
EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms());
}
TEST_F(RtpPacketHistoryTest, MinResendTime) {
static const int64_t kMinRetransmitIntervalMs = 100;
hist_.SetStorePacketsStatus(true, 10);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
size_t len = packet->size();
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
// First transmission: TimeToSendPacket() call from pacer.
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false));
fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs);
// Time has elapsed.
std::unique_ptr<RtpPacketToSend> packet_out =
hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true);
EXPECT_TRUE(packet_out);
EXPECT_EQ(len, packet_out->size());
EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms());
fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
// Time has not elapsed. Packet should be found, but no bytes copied.
EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum));
EXPECT_FALSE(
hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true));
}
TEST_F(RtpPacketHistoryTest, EarlyFirstResend) {
static const int64_t kMinRetransmitIntervalMs = 100;
hist_.SetStorePacketsStatus(true, 10);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum);
rtc::CopyOnWriteBuffer buffer = packet->Buffer();
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
// First transmission: TimeToSendPacket() call from pacer.
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum, 0, false));
fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
// Time has not elapsed, but this is the first retransmission request so
// allow anyway.
std::unique_ptr<RtpPacketToSend> packet_out =
hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true);
EXPECT_TRUE(packet_out);
EXPECT_EQ(buffer, packet_out->Buffer());
EXPECT_EQ(capture_time_ms, packet_out->capture_time_ms());
fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
// Time has not elapsed. Packet should be found, but no bytes copied.
EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum));
EXPECT_FALSE(
hist_.GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs, true));
}
TEST_F(RtpPacketHistoryTest, DynamicExpansion) {
hist_.SetStorePacketsStatus(true, 10);
// Add 4 packets, and then send them.
for (int i = 0; i < 4; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
}
for (int i = 0; i < 4; ++i) {
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false));
}
fake_clock_.AdvanceTimeMilliseconds(33);
// Add 16 packets, and then send them. History should expand to make this
// work.
for (int i = 4; i < 20; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
}
for (int i = 4; i < 20; ++i) {
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false));
}
fake_clock_.AdvanceTimeMilliseconds(100);
// Retransmit last 16 packets.
for (int i = 4; i < 20; ++i) {
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false));
}
}
TEST_F(RtpPacketHistoryTest, FullExpansion) {
static const int kSendSidePacketHistorySize = 600;
hist_.SetStorePacketsStatus(true, kSendSidePacketHistorySize);
for (size_t i = 0; i < RtpPacketHistory::kMaxCapacity + 1; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
}
fake_clock_.AdvanceTimeMilliseconds(100);
// Retransmit all packets currently in buffer.
for (size_t i = 1; i < RtpPacketHistory::kMaxCapacity + 1; ++i) {
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false));
}
}
TEST_F(RtpPacketHistoryTest, DontExpandIfPacketIsOldEnough) {
const size_t kSendSidePacketHistorySize = 600;
const int64_t kRttMs = 334;
hist_.SetStorePacketsStatus(true, kSendSidePacketHistorySize);
hist_.SetRtt(kRttMs);
// Fill up the buffer with packets.
for (size_t i = 0; i < kSendSidePacketHistorySize; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, 100, false));
}
// Move clock forward past expiration time.
fake_clock_.AdvanceTimeMilliseconds(kRttMs * 3 + 1);
// Insert a new packet and check that the old one for this index has been
// overwritten.
std::unique_ptr<RtpPacketToSend> packet =
CreateRtpPacket(kSeqNum + kSendSidePacketHistorySize);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, true);
EXPECT_FALSE(hist_.HasRtpPacket(kSeqNum));
}
TEST_F(RtpPacketHistoryTest, ExpandIfPacketTooRecentlyTransmitted) {
const size_t kSendSidePacketHistorySize = 600;
const int64_t kRttMs = 334;
hist_.SetStorePacketsStatus(true, kSendSidePacketHistorySize);
hist_.SetRtt(kRttMs);
// Fill up the buffer with packets.
for (size_t i = 0; i < kSendSidePacketHistorySize; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, kRttMs, false));
}
// Move clock forward to just before expiration time.
fake_clock_.AdvanceTimeMilliseconds(kRttMs * 3);
// Insert a new packet and verify that the old one for this index still
// exists - ie the buffer has been expanded.
std::unique_ptr<RtpPacketToSend> packet =
CreateRtpPacket(kSeqNum + kSendSidePacketHistorySize);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, true);
EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum));
}
TEST_F(RtpPacketHistoryTest, ExpandIfPacketTooRecentlyTransmittedOnFastLink) {
const size_t kSendSidePacketHistorySize = 600;
const int64_t kRttMs = 5;
hist_.SetStorePacketsStatus(true, kSendSidePacketHistorySize);
hist_.SetRtt(kRttMs);
// Fill up the buffer with packets.
for (size_t i = 0; i < kSendSidePacketHistorySize; ++i) {
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kSeqNum + i);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false);
EXPECT_TRUE(hist_.GetPacketAndSetSendTime(kSeqNum + i, kRttMs, false));
}
// Move clock forward after expiration time based on RTT, but before
// expiration time based on absolute time.
fake_clock_.AdvanceTimeMilliseconds(999);
// Insert a new packet and verify that the old one for this index still
// exists - ie the buffer has been expanded.
std::unique_ptr<RtpPacketToSend> packet =
CreateRtpPacket(kSeqNum + kSendSidePacketHistorySize);
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, true);
EXPECT_TRUE(hist_.HasRtpPacket(kSeqNum));
}
} // namespace webrtc