1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 *
10 * This file includes unit tests for the RTPPacketHistory.
11 */
12
13#include "testing/gtest/include/gtest/gtest.h"
14
15#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
16#include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
17#include "webrtc/system_wrappers/include/clock.h"
18#include "webrtc/typedefs.h"
19
20namespace webrtc {
21
22class RtpPacketHistoryTest : public ::testing::Test {
23 protected:
24  RtpPacketHistoryTest()
25     : fake_clock_(123456),
26       hist_(new RTPPacketHistory(&fake_clock_)) {
27  }
28  ~RtpPacketHistoryTest() {
29    delete hist_;
30  }
31
32  SimulatedClock fake_clock_;
33  RTPPacketHistory* hist_;
34  enum {kPayload = 127};
35  enum {kSsrc = 12345678};
36  enum {kSeqNum = 88};
37  enum {kTimestamp = 127};
38  enum {kMaxPacketLength = 1500};
39  uint8_t packet_[kMaxPacketLength];
40  uint8_t packet_out_[kMaxPacketLength];
41
42  void CreateRtpPacket(uint16_t seq_num, uint32_t ssrc, uint8_t payload,
43      uint32_t timestamp, uint8_t* array, size_t* cur_pos) {
44    array[(*cur_pos)++] = 0x80;
45    array[(*cur_pos)++] = payload;
46    array[(*cur_pos)++] = seq_num >> 8;
47    array[(*cur_pos)++] = seq_num;
48    array[(*cur_pos)++] = timestamp >> 24;
49    array[(*cur_pos)++] = timestamp >> 16;
50    array[(*cur_pos)++] = timestamp >> 8;
51    array[(*cur_pos)++] = timestamp;
52    array[(*cur_pos)++] = ssrc >> 24;
53    array[(*cur_pos)++] = ssrc >> 16;
54    array[(*cur_pos)++] = ssrc >> 8;
55    array[(*cur_pos)++] = ssrc;
56  }
57};
58
59TEST_F(RtpPacketHistoryTest, SetStoreStatus) {
60  EXPECT_FALSE(hist_->StorePackets());
61  hist_->SetStorePacketsStatus(true, 10);
62  EXPECT_TRUE(hist_->StorePackets());
63  hist_->SetStorePacketsStatus(false, 0);
64  EXPECT_FALSE(hist_->StorePackets());
65}
66
67TEST_F(RtpPacketHistoryTest, NoStoreStatus) {
68  EXPECT_FALSE(hist_->StorePackets());
69  size_t len = 0;
70  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
71  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
72  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
73                                   kAllowRetransmission));
74  // Packet should not be stored.
75  len = kMaxPacketLength;
76  int64_t time;
77  EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len,
78                                              &time));
79}
80
81TEST_F(RtpPacketHistoryTest, PutRtpPacket_TooLargePacketLength) {
82  hist_->SetStorePacketsStatus(true, 10);
83  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
84  EXPECT_EQ(-1, hist_->PutRTPPacket(packet_, kMaxPacketLength + 1,
85                                    capture_time_ms, kAllowRetransmission));
86}
87
88TEST_F(RtpPacketHistoryTest, GetRtpPacket_NotStored) {
89  hist_->SetStorePacketsStatus(true, 10);
90  size_t len = kMaxPacketLength;
91  int64_t time;
92  EXPECT_FALSE(hist_->GetPacketAndSetSendTime(0, 0, false, packet_, &len,
93                                              &time));
94}
95
96TEST_F(RtpPacketHistoryTest, PutRtpPacket) {
97  hist_->SetStorePacketsStatus(true, 10);
98  size_t len = 0;
99  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
100
101  EXPECT_FALSE(hist_->HasRTPPacket(kSeqNum));
102  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
103  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
104                                   kAllowRetransmission));
105  EXPECT_TRUE(hist_->HasRTPPacket(kSeqNum));
106}
107
108TEST_F(RtpPacketHistoryTest, GetRtpPacket) {
109  hist_->SetStorePacketsStatus(true, 10);
110  size_t len = 0;
111  int64_t capture_time_ms = 1;
112  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
113  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
114                                   kAllowRetransmission));
115
116  size_t len_out = kMaxPacketLength;
117  int64_t time;
118  EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_,
119                                             &len_out, &time));
120  EXPECT_EQ(len, len_out);
121  EXPECT_EQ(capture_time_ms, time);
122  for (size_t i = 0; i < len; i++)  {
123    EXPECT_EQ(packet_[i], packet_out_[i]);
124  }
125}
126
127TEST_F(RtpPacketHistoryTest, NoCaptureTime) {
128  hist_->SetStorePacketsStatus(true, 10);
129  size_t len = 0;
130  fake_clock_.AdvanceTimeMilliseconds(1);
131  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
132  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
133  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, -1, kAllowRetransmission));
134
135  size_t len_out = kMaxPacketLength;
136  int64_t time;
137  EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_,
138                                             &len_out, &time));
139  EXPECT_EQ(len, len_out);
140  EXPECT_EQ(capture_time_ms, time);
141  for (size_t i = 0; i < len; i++)  {
142    EXPECT_EQ(packet_[i], packet_out_[i]);
143  }
144}
145
146TEST_F(RtpPacketHistoryTest, DontRetransmit) {
147  hist_->SetStorePacketsStatus(true, 10);
148  size_t len = 0;
149  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
150  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
151  EXPECT_EQ(
152      0, hist_->PutRTPPacket(packet_, len, capture_time_ms, kDontRetransmit));
153
154  size_t len_out = kMaxPacketLength;
155  int64_t time;
156  EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_out_,
157                                             &len_out, &time));
158  EXPECT_EQ(len, len_out);
159  EXPECT_EQ(capture_time_ms, time);
160}
161
162TEST_F(RtpPacketHistoryTest, MinResendTime) {
163  static const int64_t kMinRetransmitIntervalMs = 100;
164
165  hist_->SetStorePacketsStatus(true, 10);
166  size_t len = 0;
167  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
168  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
169  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
170                                   kAllowRetransmission));
171
172  // First transmission: TimeToSendPacket() call from pacer.
173  int64_t time;
174  len = kMaxPacketLength;
175  EXPECT_TRUE(
176      hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len, &time));
177
178  fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs);
179  // Time has elapsed.
180  len = kMaxPacketLength;
181  EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs,
182                                             true, packet_, &len, &time));
183  EXPECT_GT(len, 0u);
184  EXPECT_EQ(capture_time_ms, time);
185
186  fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
187  // Time has not elapsed. Packet should be found, but no bytes copied.
188  len = kMaxPacketLength;
189  EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs,
190                                              true, packet_, &len, &time));
191}
192
193TEST_F(RtpPacketHistoryTest, EarlyFirstResend) {
194  static const int64_t kMinRetransmitIntervalMs = 100;
195
196  hist_->SetStorePacketsStatus(true, 10);
197  size_t len = 0;
198  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
199  CreateRtpPacket(kSeqNum, kSsrc, kPayload, kTimestamp, packet_, &len);
200  EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
201                                   kAllowRetransmission));
202
203  // First transmission: TimeToSendPacket() call from pacer.
204  int64_t time;
205  len = kMaxPacketLength;
206  EXPECT_TRUE(
207      hist_->GetPacketAndSetSendTime(kSeqNum, 0, false, packet_, &len, &time));
208
209  fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
210  // Time has not elapsed, but this is the first retransmission request so
211  // allow anyway.
212  len = kMaxPacketLength;
213  EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs,
214                                             true, packet_, &len, &time));
215  EXPECT_GT(len, 0u);
216  EXPECT_EQ(capture_time_ms, time);
217
218  fake_clock_.AdvanceTimeMilliseconds(kMinRetransmitIntervalMs - 1);
219  // Time has not elapsed. Packet should be found, but no bytes copied.
220  len = kMaxPacketLength;
221  EXPECT_FALSE(hist_->GetPacketAndSetSendTime(kSeqNum, kMinRetransmitIntervalMs,
222                                              true, packet_, &len, &time));
223}
224
225TEST_F(RtpPacketHistoryTest, DynamicExpansion) {
226  hist_->SetStorePacketsStatus(true, 10);
227  size_t len;
228  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
229  int64_t time;
230
231  // Add 4 packets, and then send them.
232  for (int i = 0; i < 4; ++i) {
233    len = 0;
234    CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len);
235    EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
236                                     kAllowRetransmission));
237  }
238  for (int i = 0; i < 4; ++i) {
239    len = kMaxPacketLength;
240    EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_,
241                                               &len, &time));
242  }
243  capture_time_ms += 33;
244
245  // Add 16 packets, and then send them. History should expand to make this
246  // work.
247  for (int i = 4; i < 20; ++i) {
248    len = 0;
249    CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len);
250    EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
251                                     kAllowRetransmission));
252  }
253  for (int i = 4; i < 20; ++i) {
254    len = kMaxPacketLength;
255    EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_,
256                                               &len, &time));
257  }
258
259  fake_clock_.AdvanceTimeMilliseconds(100);
260
261  // Retransmit last 16 packets.
262  for (int i = 4; i < 20; ++i) {
263    len = kMaxPacketLength;
264    EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_,
265                                               &len, &time));
266  }
267}
268
269TEST_F(RtpPacketHistoryTest, FullExpansion) {
270  static const int kSendSidePacketHistorySize = 600;
271  hist_->SetStorePacketsStatus(true, kSendSidePacketHistorySize);
272  size_t len;
273  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
274  int64_t time;
275  for (size_t i = 0; i < kMaxHistoryCapacity + 1; ++i) {
276    len = 0;
277    CreateRtpPacket(kSeqNum + i, kSsrc, kPayload, kTimestamp, packet_, &len);
278    EXPECT_EQ(0, hist_->PutRTPPacket(packet_, len, capture_time_ms,
279                                     kAllowRetransmission));
280  }
281
282  fake_clock_.AdvanceTimeMilliseconds(100);
283
284  // Retransmit all packets currently in buffer.
285  for (size_t i = 1; i < kMaxHistoryCapacity + 1; ++i) {
286    len = kMaxPacketLength;
287    EXPECT_TRUE(hist_->GetPacketAndSetSendTime(kSeqNum + i, 100, false, packet_,
288                                               &len, &time));
289  }
290}
291
292}  // namespace webrtc
293