1/*
2 *  Copyright (c) 2013 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
11#include "testing/gtest/include/gtest/gtest.h"
12
13#include "webrtc/base/scoped_ptr.h"
14#include "webrtc/common_types.h"
15#include "webrtc/modules/remote_bitrate_estimator/inter_arrival.h"
16
17namespace webrtc {
18namespace testing {
19
20enum {
21  kTimestampGroupLengthUs = 5000,
22  kMinStep = 20,
23  kTriggerNewGroupUs = kTimestampGroupLengthUs + kMinStep,
24  kBurstThresholdMs = 5,
25  kAbsSendTimeFraction = 18,
26  kAbsSendTimeInterArrivalUpshift = 8,
27  kInterArrivalShift = kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift,
28};
29
30const double kRtpTimestampToMs = 1.0 / 90.0;
31const double kAstToMs = 1000.0 / static_cast<double>(1 << kInterArrivalShift);
32
33class InterArrivalTest : public ::testing::Test {
34 protected:
35  virtual void SetUp() {
36    inter_arrival_rtp_.reset(new InterArrival(
37        MakeRtpTimestamp(kTimestampGroupLengthUs),
38        kRtpTimestampToMs,
39        true));
40    inter_arrival_ast_.reset(new InterArrival(
41        MakeAbsSendTime(kTimestampGroupLengthUs),
42        kAstToMs,
43        true));
44  }
45
46  // Test that neither inter_arrival instance complete the timestamp group from
47  // the given data.
48  void ExpectFalse(int64_t timestamp_us, int64_t arrival_time_ms,
49                   size_t packet_size) {
50    InternalExpectFalse(inter_arrival_rtp_.get(),
51                        MakeRtpTimestamp(timestamp_us), arrival_time_ms,
52                        packet_size);
53    InternalExpectFalse(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
54                        arrival_time_ms, packet_size);
55  }
56
57  // Test that both inter_arrival instances complete the timestamp group from
58  // the given data and that all returned deltas are as expected (except
59  // timestamp delta, which is rounded from us to different ranges and must
60  // match within an interval, given in |timestamp_near].
61  void ExpectTrue(int64_t timestamp_us, int64_t arrival_time_ms,
62                  size_t packet_size, int64_t expected_timestamp_delta_us,
63                  int64_t expected_arrival_time_delta_ms,
64                  int expected_packet_size_delta,
65                  uint32_t timestamp_near) {
66    InternalExpectTrue(inter_arrival_rtp_.get(), MakeRtpTimestamp(timestamp_us),
67                       arrival_time_ms, packet_size,
68                       MakeRtpTimestamp(expected_timestamp_delta_us),
69                       expected_arrival_time_delta_ms,
70                       expected_packet_size_delta, timestamp_near);
71    InternalExpectTrue(inter_arrival_ast_.get(), MakeAbsSendTime(timestamp_us),
72                       arrival_time_ms, packet_size,
73                       MakeAbsSendTime(expected_timestamp_delta_us),
74                       expected_arrival_time_delta_ms,
75                       expected_packet_size_delta, timestamp_near << 8);
76  }
77
78  void WrapTestHelper(int64_t wrap_start_us, uint32_t timestamp_near,
79                      bool unorderly_within_group) {
80    // Step through the range of a 32 bit int, 1/4 at a time to not cause
81    // packets close to wraparound to be judged as out of order.
82
83    // G1
84    int64_t arrival_time = 17;
85    ExpectFalse(0, arrival_time, 1);
86
87    // G2
88    arrival_time += kBurstThresholdMs + 1;
89    ExpectFalse(wrap_start_us / 4, arrival_time, 1);
90
91    // G3
92    arrival_time += kBurstThresholdMs + 1;
93    ExpectTrue(wrap_start_us / 2, arrival_time, 1,
94               wrap_start_us / 4, 6, 0,   // Delta G2-G1
95               0);
96
97    // G4
98    arrival_time += kBurstThresholdMs + 1;
99    int64_t g4_arrival_time = arrival_time;
100    ExpectTrue(wrap_start_us / 2 + wrap_start_us / 4, arrival_time, 1,
101               wrap_start_us / 4, 6, 0,   // Delta G3-G2
102               timestamp_near);
103
104    // G5
105    arrival_time += kBurstThresholdMs + 1;
106    ExpectTrue(wrap_start_us, arrival_time, 2,
107               wrap_start_us / 4, 6, 0,   // Delta G4-G3
108               timestamp_near);
109    for (int i = 0; i < 10; ++i) {
110      // Slowly step across the wrap point.
111      arrival_time += kBurstThresholdMs + 1;
112      if (unorderly_within_group) {
113        // These packets arrive with timestamps in decreasing order but are
114        // nevertheless accumulated to group because their timestamps are higher
115        // than the initial timestamp of the group.
116        ExpectFalse(wrap_start_us + kMinStep * (9 - i), arrival_time, 1);
117      } else {
118        ExpectFalse(wrap_start_us + kMinStep * i, arrival_time, 1);
119      }
120    }
121    int64_t g5_arrival_time = arrival_time;
122
123    // This packet is out of order and should be dropped.
124    arrival_time += kBurstThresholdMs + 1;
125    ExpectFalse(wrap_start_us - 100, arrival_time, 100);
126
127    // G6
128    arrival_time += kBurstThresholdMs + 1;
129    int64_t g6_arrival_time = arrival_time;
130    ExpectTrue(wrap_start_us + kTriggerNewGroupUs, arrival_time, 10,
131               wrap_start_us / 4 + 9 * kMinStep,
132               g5_arrival_time - g4_arrival_time,
133               (2 + 10) - 1,  // Delta G5-G4
134               timestamp_near);
135
136    // This packet is out of order and should be dropped.
137    arrival_time += kBurstThresholdMs + 1;
138    ExpectFalse(wrap_start_us + kTimestampGroupLengthUs, arrival_time, 100);
139
140    // G7
141    arrival_time += kBurstThresholdMs + 1;
142    ExpectTrue(wrap_start_us + 2 * kTriggerNewGroupUs,
143               arrival_time, 100,
144               // Delta G6-G5
145               kTriggerNewGroupUs - 9 * kMinStep,
146               g6_arrival_time - g5_arrival_time,
147               10 - (2 + 10),
148               timestamp_near);
149  }
150
151 private:
152  static uint32_t MakeRtpTimestamp(int64_t us) {
153    return static_cast<uint32_t>(static_cast<uint64_t>(us * 90 + 500) / 1000);
154  }
155
156  static uint32_t MakeAbsSendTime(int64_t us) {
157    uint32_t absolute_send_time = static_cast<uint32_t>(
158        ((static_cast<uint64_t>(us) << 18) + 500000) / 1000000) & 0x00FFFFFFul;
159    return absolute_send_time << 8;
160  }
161
162  static void InternalExpectFalse(InterArrival* inter_arrival,
163                                  uint32_t timestamp, int64_t arrival_time_ms,
164                                  size_t packet_size) {
165    uint32_t dummy_timestamp = 101;
166    int64_t dummy_arrival_time_ms = 303;
167    int dummy_packet_size = 909;
168    bool computed = inter_arrival->ComputeDeltas(timestamp,
169                                                 arrival_time_ms,
170                                                 packet_size,
171                                                 &dummy_timestamp,
172                                                 &dummy_arrival_time_ms,
173                                                 &dummy_packet_size);
174    EXPECT_EQ(computed, false);
175    EXPECT_EQ(101ul, dummy_timestamp);
176    EXPECT_EQ(303, dummy_arrival_time_ms);
177    EXPECT_EQ(909, dummy_packet_size);
178  }
179
180  static void InternalExpectTrue(InterArrival* inter_arrival,
181                                 uint32_t timestamp, int64_t arrival_time_ms,
182                                 size_t packet_size,
183                                 uint32_t expected_timestamp_delta,
184                                 int64_t expected_arrival_time_delta_ms,
185                                 int expected_packet_size_delta,
186                                 uint32_t timestamp_near) {
187    uint32_t delta_timestamp = 101;
188    int64_t delta_arrival_time_ms = 303;
189    int delta_packet_size = 909;
190    bool computed = inter_arrival->ComputeDeltas(timestamp,
191                                                 arrival_time_ms,
192                                                 packet_size,
193                                                 &delta_timestamp,
194                                                 &delta_arrival_time_ms,
195                                                 &delta_packet_size);
196    EXPECT_EQ(true, computed);
197    EXPECT_NEAR(expected_timestamp_delta, delta_timestamp, timestamp_near);
198    EXPECT_EQ(expected_arrival_time_delta_ms, delta_arrival_time_ms);
199    EXPECT_EQ(expected_packet_size_delta, delta_packet_size);
200  }
201
202  rtc::scoped_ptr<InterArrival> inter_arrival_rtp_;
203  rtc::scoped_ptr<InterArrival> inter_arrival_ast_;
204};
205
206TEST_F(InterArrivalTest, FirstPacket) {
207  ExpectFalse(0, 17, 1);
208}
209
210TEST_F(InterArrivalTest, FirstGroup) {
211  // G1
212  int64_t arrival_time = 17;
213  int64_t g1_arrival_time = arrival_time;
214  ExpectFalse(0, arrival_time, 1);
215
216  // G2
217  arrival_time += kBurstThresholdMs + 1;
218  int64_t g2_arrival_time = arrival_time;
219  ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
220
221  // G3
222  // Only once the first packet of the third group arrives, do we see the deltas
223  // between the first two.
224  arrival_time += kBurstThresholdMs + 1;
225  ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
226             // Delta G2-G1
227             kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
228             0);
229}
230
231TEST_F(InterArrivalTest, SecondGroup) {
232  // G1
233  int64_t arrival_time = 17;
234  int64_t g1_arrival_time = arrival_time;
235  ExpectFalse(0, arrival_time, 1);
236
237  // G2
238  arrival_time += kBurstThresholdMs + 1;
239  int64_t g2_arrival_time = arrival_time;
240  ExpectFalse(kTriggerNewGroupUs, arrival_time, 2);
241
242  // G3
243  arrival_time += kBurstThresholdMs + 1;
244  int64_t g3_arrival_time = arrival_time;
245  ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 1,
246             // Delta G2-G1
247             kTriggerNewGroupUs, g2_arrival_time - g1_arrival_time, 1,
248             0);
249
250  // G4
251  // First packet of 4th group yields deltas between group 2 and 3.
252  arrival_time += kBurstThresholdMs + 1;
253  ExpectTrue(3 * kTriggerNewGroupUs, arrival_time, 2,
254             // Delta G3-G2
255             kTriggerNewGroupUs, g3_arrival_time - g2_arrival_time, -1,
256             0);
257}
258
259TEST_F(InterArrivalTest, AccumulatedGroup) {
260  // G1
261  int64_t arrival_time = 17;
262  int64_t g1_arrival_time = arrival_time;
263  ExpectFalse(0, arrival_time, 1);
264
265  // G2
266  arrival_time += kBurstThresholdMs + 1;
267  ExpectFalse(kTriggerNewGroupUs, 28, 2);
268  int64_t timestamp = kTriggerNewGroupUs;
269  for (int i = 0; i < 10; ++i) {
270    // A bunch of packets arriving within the same group.
271    arrival_time += kBurstThresholdMs + 1;
272    timestamp += kMinStep;
273    ExpectFalse(timestamp, arrival_time, 1);
274  }
275  int64_t g2_arrival_time = arrival_time;
276  int64_t g2_timestamp = timestamp;
277
278  // G3
279  arrival_time = 500;
280  ExpectTrue(2 * kTriggerNewGroupUs, arrival_time, 100,
281             g2_timestamp, g2_arrival_time - g1_arrival_time,
282             (2 + 10) - 1,   // Delta G2-G1
283             0);
284}
285
286TEST_F(InterArrivalTest, OutOfOrderPacket) {
287  // G1
288  int64_t arrival_time = 17;
289  int64_t timestamp = 0;
290  ExpectFalse(timestamp, arrival_time, 1);
291  int64_t g1_timestamp = timestamp;
292  int64_t g1_arrival_time = arrival_time;
293
294  // G2
295  arrival_time += 11;
296  timestamp += kTriggerNewGroupUs;
297  ExpectFalse(timestamp, 28, 2);
298  for (int i = 0; i < 10; ++i) {
299    arrival_time += kBurstThresholdMs + 1;
300    timestamp += kMinStep;
301    ExpectFalse(timestamp, arrival_time, 1);
302  }
303  int64_t g2_timestamp = timestamp;
304  int64_t g2_arrival_time = arrival_time;
305
306  // This packet is out of order and should be dropped.
307  arrival_time = 281;
308  ExpectFalse(g1_timestamp, arrival_time, 100);
309
310  // G3
311  arrival_time = 500;
312  timestamp = 2 * kTriggerNewGroupUs;
313  ExpectTrue(timestamp, arrival_time, 100,
314             // Delta G2-G1
315             g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
316             (2 + 10) - 1,
317             0);
318}
319
320TEST_F(InterArrivalTest, OutOfOrderWithinGroup) {
321  // G1
322  int64_t arrival_time = 17;
323  int64_t timestamp = 0;
324  ExpectFalse(timestamp, arrival_time, 1);
325  int64_t g1_timestamp = timestamp;
326  int64_t g1_arrival_time = arrival_time;
327
328  // G2
329  timestamp += kTriggerNewGroupUs;
330  arrival_time += 11;
331  ExpectFalse(kTriggerNewGroupUs, 28, 2);
332  timestamp += 10 * kMinStep;
333  int64_t g2_timestamp = timestamp;
334  for (int i = 0; i < 10; ++i) {
335    // These packets arrive with timestamps in decreasing order but are
336    // nevertheless accumulated to group because their timestamps are higher
337    // than the initial timestamp of the group.
338    arrival_time += kBurstThresholdMs + 1;
339    ExpectFalse(timestamp, arrival_time, 1);
340    timestamp -= kMinStep;
341  }
342  int64_t g2_arrival_time = arrival_time;
343
344  // However, this packet is deemed out of order and should be dropped.
345  arrival_time = 281;
346  timestamp = g1_timestamp;
347  ExpectFalse(timestamp, arrival_time, 100);
348
349  // G3
350  timestamp = 2 * kTriggerNewGroupUs;
351  arrival_time = 500;
352  ExpectTrue(timestamp, arrival_time, 100,
353             g2_timestamp - g1_timestamp, g2_arrival_time - g1_arrival_time,
354             (2 + 10) - 1,
355             0);
356}
357
358TEST_F(InterArrivalTest, TwoBursts) {
359  // G1
360  int64_t g1_arrival_time = 17;
361  ExpectFalse(0, g1_arrival_time, 1);
362
363  // G2
364  int64_t timestamp = kTriggerNewGroupUs;
365  int64_t arrival_time = 100;  // Simulate no packets arriving for 100 ms.
366  for (int i = 0; i < 10; ++i) {
367    // A bunch of packets arriving in one burst (within 5 ms apart).
368    timestamp += 30000;
369    arrival_time += kBurstThresholdMs;
370    ExpectFalse(timestamp, arrival_time, 1);
371  }
372  int64_t g2_arrival_time = arrival_time;
373  int64_t g2_timestamp = timestamp;
374
375  // G3
376  timestamp += 30000;
377  arrival_time += kBurstThresholdMs + 1;
378  ExpectTrue(timestamp, arrival_time, 100,
379             g2_timestamp, g2_arrival_time - g1_arrival_time,
380             10 - 1,  // Delta G2-G1
381             0);
382}
383
384
385TEST_F(InterArrivalTest, NoBursts) {
386  // G1
387  ExpectFalse(0, 17, 1);
388
389  // G2
390  int64_t timestamp = kTriggerNewGroupUs;
391  int64_t arrival_time = 28;
392  ExpectFalse(timestamp, arrival_time, 2);
393
394  // G3
395  ExpectTrue(kTriggerNewGroupUs + 30000, arrival_time + kBurstThresholdMs + 1,
396             100, timestamp - 0, arrival_time - 17,
397             2 - 1,  // Delta G2-G1
398             0);
399}
400
401// Yields 0xfffffffe when converted to internal representation in
402// inter_arrival_rtp_ and inter_arrival_ast_ respectively.
403static const int64_t kStartRtpTimestampWrapUs = 47721858827;
404static const int64_t kStartAbsSendTimeWrapUs = 63999995;
405
406TEST_F(InterArrivalTest, RtpTimestampWrap) {
407  WrapTestHelper(kStartRtpTimestampWrapUs, 1, false);
408}
409
410TEST_F(InterArrivalTest, AbsSendTimeWrap) {
411  WrapTestHelper(kStartAbsSendTimeWrapUs, 1, false);
412}
413
414TEST_F(InterArrivalTest, RtpTimestampWrapOutOfOrderWithinGroup) {
415  WrapTestHelper(kStartRtpTimestampWrapUs, 1, true);
416}
417
418TEST_F(InterArrivalTest, AbsSendTimeWrapOutOfOrderWithinGroup) {
419  WrapTestHelper(kStartAbsSendTimeWrapUs, 1, true);
420}
421}  // namespace testing
422}  // namespace webrtc
423