mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-15 23:01:21 +01:00

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}
295 lines
11 KiB
C++
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
|