/* * 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 #include #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 CreateRtpPacket(uint16_t seq_num) { // Payload, ssrc, timestamp and extensions are irrelevant for this tests. std::unique_ptr 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 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 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 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 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 packet = CreateRtpPacket(kSeqNum); packet->set_capture_time_ms(-1); rtc::CopyOnWriteBuffer buffer = packet->Buffer(); hist_.PutRtpPacket(std::move(packet), kAllowRetransmission, false); std::unique_ptr 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 packet = CreateRtpPacket(kSeqNum); rtc::CopyOnWriteBuffer buffer = packet->Buffer(); hist_.PutRtpPacket(std::move(packet), kDontRetransmit, false); std::unique_ptr 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 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 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 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 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 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 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 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)); } } } // namespace webrtc