1 /*
2 * Copyright (c) 2015 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 "webrtc/modules/pacing/packet_router.h"
12 #include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h"
13 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
14 #include "webrtc/system_wrappers/include/clock.h"
15 #include "webrtc/test/gmock.h"
16 #include "webrtc/test/gtest.h"
17
18 using ::testing::_;
19 using ::testing::InSequence;
20 using ::testing::Invoke;
21 using ::testing::Return;
22
23 namespace webrtc {
24
25 class MockPacketRouter : public PacketRouter {
26 public:
27 MOCK_METHOD1(SendFeedback, bool(rtcp::TransportFeedback* packet));
28 };
29
30 class RemoteEstimatorProxyTest : public ::testing::Test {
31 public:
RemoteEstimatorProxyTest()32 RemoteEstimatorProxyTest() : clock_(0), proxy_(&clock_, &router_) {}
33
34 protected:
IncomingPacket(uint16_t seq,int64_t time_ms)35 void IncomingPacket(uint16_t seq, int64_t time_ms) {
36 RTPHeader header;
37 header.extension.hasTransportSequenceNumber = true;
38 header.extension.transportSequenceNumber = seq;
39 header.ssrc = kMediaSsrc;
40 proxy_.IncomingPacket(time_ms, kDefaultPacketSize, header);
41 }
42
Process()43 void Process() {
44 clock_.AdvanceTimeMilliseconds(
45 RemoteEstimatorProxy::kDefaultSendIntervalMs);
46 proxy_.Process();
47 }
48
49 SimulatedClock clock_;
50 ::testing::StrictMock<MockPacketRouter> router_;
51 RemoteEstimatorProxy proxy_;
52
53 const size_t kDefaultPacketSize = 100;
54 const uint32_t kMediaSsrc = 456;
55 const uint16_t kBaseSeq = 10;
56 const int64_t kBaseTimeMs = 123;
57 const int64_t kMaxSmallDeltaMs =
58 (rtcp::TransportFeedback::kDeltaScaleFactor * 0xFF) / 1000;
59 };
60
TEST_F(RemoteEstimatorProxyTest,SendsSinglePacketFeedback)61 TEST_F(RemoteEstimatorProxyTest, SendsSinglePacketFeedback) {
62 IncomingPacket(kBaseSeq, kBaseTimeMs);
63
64 EXPECT_CALL(router_, SendFeedback(_))
65 .Times(1)
66 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
67 packet->Build();
68 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
69 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
70
71 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
72 packet->GetStatusVector();
73 EXPECT_EQ(1u, status_vec.size());
74 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
75 status_vec[0]);
76 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
77 EXPECT_EQ(1u, delta_vec.size());
78 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
79 return true;
80 }));
81
82 Process();
83 }
84
TEST_F(RemoteEstimatorProxyTest,DuplicatedPackets)85 TEST_F(RemoteEstimatorProxyTest, DuplicatedPackets) {
86 IncomingPacket(kBaseSeq, kBaseTimeMs);
87 IncomingPacket(kBaseSeq, kBaseTimeMs + 1000);
88
89 EXPECT_CALL(router_, SendFeedback(_))
90 .Times(1)
91 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
92 packet->Build();
93 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
94 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
95
96 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
97 packet->GetStatusVector();
98 EXPECT_EQ(1u, status_vec.size());
99 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
100 status_vec[0]);
101 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
102 EXPECT_EQ(1u, delta_vec.size());
103 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
104 return true;
105 }));
106
107 Process();
108 }
109
TEST_F(RemoteEstimatorProxyTest,FeedbackWithMissingStart)110 TEST_F(RemoteEstimatorProxyTest, FeedbackWithMissingStart) {
111 // First feedback.
112 IncomingPacket(kBaseSeq, kBaseTimeMs);
113 IncomingPacket(kBaseSeq + 1, kBaseTimeMs + 1000);
114 EXPECT_CALL(router_, SendFeedback(_)).Times(1).WillOnce(Return(true));
115 Process();
116
117 // Second feedback starts with a missing packet (DROP kBaseSeq + 2).
118 IncomingPacket(kBaseSeq + 3, kBaseTimeMs + 3000);
119
120 EXPECT_CALL(router_, SendFeedback(_))
121 .Times(1)
122 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
123 packet->Build();
124 EXPECT_EQ(kBaseSeq + 2, packet->GetBaseSequence());
125 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
126
127 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
128 packet->GetStatusVector();
129 EXPECT_EQ(2u, status_vec.size());
130 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kNotReceived,
131 status_vec[0]);
132 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
133 status_vec[1]);
134 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
135 EXPECT_EQ(1u, delta_vec.size());
136 EXPECT_EQ(kBaseTimeMs + 3000,
137 (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
138 return true;
139 }));
140
141 Process();
142 }
143
TEST_F(RemoteEstimatorProxyTest,SendsFeedbackWithVaryingDeltas)144 TEST_F(RemoteEstimatorProxyTest, SendsFeedbackWithVaryingDeltas) {
145 IncomingPacket(kBaseSeq, kBaseTimeMs);
146 IncomingPacket(kBaseSeq + 1, kBaseTimeMs + kMaxSmallDeltaMs);
147 IncomingPacket(kBaseSeq + 2, kBaseTimeMs + (2 * kMaxSmallDeltaMs) + 1);
148
149 EXPECT_CALL(router_, SendFeedback(_))
150 .Times(1)
151 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
152 packet->Build();
153 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
154 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
155
156 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
157 packet->GetStatusVector();
158 EXPECT_EQ(3u, status_vec.size());
159 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
160 status_vec[0]);
161 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
162 status_vec[1]);
163 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedLargeDelta,
164 status_vec[2]);
165
166 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
167 EXPECT_EQ(3u, delta_vec.size());
168 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
169 EXPECT_EQ(kMaxSmallDeltaMs, delta_vec[1] / 1000);
170 EXPECT_EQ(kMaxSmallDeltaMs + 1, delta_vec[2] / 1000);
171 return true;
172 }));
173
174 Process();
175 }
176
TEST_F(RemoteEstimatorProxyTest,SendsFragmentedFeedback)177 TEST_F(RemoteEstimatorProxyTest, SendsFragmentedFeedback) {
178 const int64_t kTooLargeDelta =
179 rtcp::TransportFeedback::kDeltaScaleFactor * (1 << 16);
180
181 IncomingPacket(kBaseSeq, kBaseTimeMs);
182 IncomingPacket(kBaseSeq + 1, kBaseTimeMs + kTooLargeDelta);
183
184 InSequence s;
185 EXPECT_CALL(router_, SendFeedback(_))
186 .Times(1)
187 .WillOnce(Invoke([kTooLargeDelta, this](rtcp::TransportFeedback* packet) {
188 packet->Build();
189 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
190 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
191
192 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
193 packet->GetStatusVector();
194 EXPECT_EQ(1u, status_vec.size());
195 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
196 status_vec[0]);
197 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
198 EXPECT_EQ(1u, delta_vec.size());
199 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
200 return true;
201 }))
202 .RetiresOnSaturation();
203
204 EXPECT_CALL(router_, SendFeedback(_))
205 .Times(1)
206 .WillOnce(Invoke([kTooLargeDelta, this](rtcp::TransportFeedback* packet) {
207 packet->Build();
208 EXPECT_EQ(kBaseSeq + 1, packet->GetBaseSequence());
209 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
210
211 std::vector<rtcp::TransportFeedback::StatusSymbol> status_vec =
212 packet->GetStatusVector();
213 EXPECT_EQ(1u, status_vec.size());
214 EXPECT_EQ(rtcp::TransportFeedback::StatusSymbol::kReceivedSmallDelta,
215 status_vec[0]);
216 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
217 EXPECT_EQ(1u, delta_vec.size());
218 EXPECT_EQ(kBaseTimeMs + kTooLargeDelta,
219 (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
220 return true;
221 }))
222 .RetiresOnSaturation();
223
224 Process();
225 }
226
TEST_F(RemoteEstimatorProxyTest,GracefullyHandlesReorderingAndWrap)227 TEST_F(RemoteEstimatorProxyTest, GracefullyHandlesReorderingAndWrap) {
228 const int64_t kDeltaMs = 1000;
229 const uint16_t kLargeSeq = 62762;
230 IncomingPacket(kBaseSeq, kBaseTimeMs);
231 IncomingPacket(kLargeSeq, kBaseTimeMs + kDeltaMs);
232
233 EXPECT_CALL(router_, SendFeedback(_))
234 .Times(1)
235 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
236 packet->Build();
237 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
238 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
239
240 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
241 EXPECT_EQ(1u, delta_vec.size());
242 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
243 return true;
244 }));
245
246 Process();
247 }
248
TEST_F(RemoteEstimatorProxyTest,ResendsTimestampsOnReordering)249 TEST_F(RemoteEstimatorProxyTest, ResendsTimestampsOnReordering) {
250 IncomingPacket(kBaseSeq, kBaseTimeMs);
251 IncomingPacket(kBaseSeq + 2, kBaseTimeMs + 2);
252
253 EXPECT_CALL(router_, SendFeedback(_))
254 .Times(1)
255 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
256 packet->Build();
257 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
258 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
259
260 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
261 EXPECT_EQ(2u, delta_vec.size());
262 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
263 EXPECT_EQ(2, delta_vec[1] / 1000);
264 return true;
265 }));
266
267 Process();
268
269 IncomingPacket(kBaseSeq + 1, kBaseTimeMs + 1);
270
271 EXPECT_CALL(router_, SendFeedback(_))
272 .Times(1)
273 .WillOnce(Invoke([this](rtcp::TransportFeedback* packet) {
274 packet->Build();
275 EXPECT_EQ(kBaseSeq + 1, packet->GetBaseSequence());
276 EXPECT_EQ(kMediaSsrc, packet->media_ssrc());
277
278 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
279 EXPECT_EQ(2u, delta_vec.size());
280 EXPECT_EQ(kBaseTimeMs + 1,
281 (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
282 EXPECT_EQ(1, delta_vec[1] / 1000);
283 return true;
284 }));
285
286 Process();
287 }
288
TEST_F(RemoteEstimatorProxyTest,RemovesTimestampsOutOfScope)289 TEST_F(RemoteEstimatorProxyTest, RemovesTimestampsOutOfScope) {
290 const int64_t kTimeoutTimeMs =
291 kBaseTimeMs + RemoteEstimatorProxy::kBackWindowMs;
292
293 IncomingPacket(kBaseSeq + 2, kBaseTimeMs);
294
295 EXPECT_CALL(router_, SendFeedback(_))
296 .Times(1)
297 .WillOnce(Invoke([kTimeoutTimeMs, this](rtcp::TransportFeedback* packet) {
298 packet->Build();
299 EXPECT_EQ(kBaseSeq + 2, packet->GetBaseSequence());
300
301 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
302 EXPECT_EQ(1u, delta_vec.size());
303 EXPECT_EQ(kBaseTimeMs, (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
304 return true;
305 }));
306
307 Process();
308
309 IncomingPacket(kBaseSeq + 3, kTimeoutTimeMs); // kBaseSeq + 2 times out here.
310
311 EXPECT_CALL(router_, SendFeedback(_))
312 .Times(1)
313 .WillOnce(Invoke([kTimeoutTimeMs, this](rtcp::TransportFeedback* packet) {
314 packet->Build();
315 EXPECT_EQ(kBaseSeq + 3, packet->GetBaseSequence());
316
317 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
318 EXPECT_EQ(1u, delta_vec.size());
319 EXPECT_EQ(kTimeoutTimeMs,
320 (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
321 return true;
322 }));
323
324 Process();
325
326 // New group, with sequence starting below the first so that they may be
327 // retransmitted.
328 IncomingPacket(kBaseSeq, kBaseTimeMs - 1);
329 IncomingPacket(kBaseSeq + 1, kTimeoutTimeMs - 1);
330
331 EXPECT_CALL(router_, SendFeedback(_))
332 .Times(1)
333 .WillOnce(Invoke([kTimeoutTimeMs, this](rtcp::TransportFeedback* packet) {
334 packet->Build();
335 EXPECT_EQ(kBaseSeq, packet->GetBaseSequence());
336
337 // Four status entries (kBaseSeq + 3 missing).
338 EXPECT_EQ(4u, packet->GetStatusVector().size());
339
340 // Only three actual timestamps.
341 std::vector<int64_t> delta_vec = packet->GetReceiveDeltasUs();
342 EXPECT_EQ(3u, delta_vec.size());
343 EXPECT_EQ(kBaseTimeMs - 1,
344 (packet->GetBaseTimeUs() + delta_vec[0]) / 1000);
345 EXPECT_EQ(kTimeoutTimeMs - kBaseTimeMs, delta_vec[1] / 1000);
346 EXPECT_EQ(1, delta_vec[2] / 1000);
347 return true;
348 }));
349
350 Process();
351 }
352
TEST_F(RemoteEstimatorProxyTest,TimeUntilNextProcessIsZeroBeforeFirstProcess)353 TEST_F(RemoteEstimatorProxyTest, TimeUntilNextProcessIsZeroBeforeFirstProcess) {
354 EXPECT_EQ(0, proxy_.TimeUntilNextProcess());
355 }
356
TEST_F(RemoteEstimatorProxyTest,TimeUntilNextProcessIsDefaultOnUnkownBitrate)357 TEST_F(RemoteEstimatorProxyTest, TimeUntilNextProcessIsDefaultOnUnkownBitrate) {
358 Process();
359 EXPECT_EQ(RemoteEstimatorProxy::kDefaultSendIntervalMs,
360 proxy_.TimeUntilNextProcess());
361 }
362
TEST_F(RemoteEstimatorProxyTest,TimeUntilNextProcessIsMinIntervalOn300kbps)363 TEST_F(RemoteEstimatorProxyTest, TimeUntilNextProcessIsMinIntervalOn300kbps) {
364 Process();
365 proxy_.OnBitrateChanged(300000);
366 EXPECT_EQ(RemoteEstimatorProxy::kMinSendIntervalMs,
367 proxy_.TimeUntilNextProcess());
368 }
369
TEST_F(RemoteEstimatorProxyTest,TimeUntilNextProcessIsMaxIntervalOn0kbps)370 TEST_F(RemoteEstimatorProxyTest, TimeUntilNextProcessIsMaxIntervalOn0kbps) {
371 Process();
372 // TimeUntilNextProcess should be limited by |kMaxSendIntervalMs| when
373 // bitrate is small. We choose 0 bps as a special case, which also tests
374 // erroneous behaviors like division-by-zero.
375 proxy_.OnBitrateChanged(0);
376 EXPECT_EQ(RemoteEstimatorProxy::kMaxSendIntervalMs,
377 proxy_.TimeUntilNextProcess());
378 }
379
TEST_F(RemoteEstimatorProxyTest,TimeUntilNextProcessIsMaxIntervalOn20kbps)380 TEST_F(RemoteEstimatorProxyTest, TimeUntilNextProcessIsMaxIntervalOn20kbps) {
381 Process();
382 proxy_.OnBitrateChanged(20000);
383 EXPECT_EQ(RemoteEstimatorProxy::kMaxSendIntervalMs,
384 proxy_.TimeUntilNextProcess());
385 }
386
TEST_F(RemoteEstimatorProxyTest,TwccReportsUse5PercentOfAvailableBandwidth)387 TEST_F(RemoteEstimatorProxyTest, TwccReportsUse5PercentOfAvailableBandwidth) {
388 Process();
389 proxy_.OnBitrateChanged(80000);
390 // 80kbps * 0.05 = TwccReportSize(68B * 8b/B) * 1000ms / SendInterval(136ms)
391 EXPECT_EQ(136, proxy_.TimeUntilNextProcess());
392 }
393
394 } // namespace webrtc
395