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 "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
12
13 #include <limits>
14 #include <memory>
15 #include <utility>
16
17 #include "modules/rtp_rtcp/source/byte_io.h"
18 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
19 #include "test/gmock.h"
20 #include "test/gtest.h"
21
22 namespace webrtc {
23 namespace {
24
25 using rtcp::TransportFeedback;
26 using ::testing::ElementsAreArray;
27
28 static const int kHeaderSize = 20;
29 static const int kStatusChunkSize = 2;
30 static const int kSmallDeltaSize = 1;
31 static const int kLargeDeltaSize = 2;
32
33 static const int64_t kDeltaLimit = 0xFF * TransportFeedback::kDeltaScaleFactor;
34
35 class FeedbackTester {
36 public:
FeedbackTester()37 FeedbackTester() : FeedbackTester(true) {}
FeedbackTester(bool include_timestamps)38 explicit FeedbackTester(bool include_timestamps)
39 : expected_size_(kAnySize),
40 default_delta_(TransportFeedback::kDeltaScaleFactor * 4),
41 include_timestamps_(include_timestamps) {}
42
WithExpectedSize(size_t expected_size)43 void WithExpectedSize(size_t expected_size) {
44 expected_size_ = expected_size;
45 }
46
WithDefaultDelta(int64_t delta)47 void WithDefaultDelta(int64_t delta) { default_delta_ = delta; }
48
WithInput(const uint16_t received_seq[],const int64_t received_ts[],uint16_t length)49 void WithInput(const uint16_t received_seq[],
50 const int64_t received_ts[],
51 uint16_t length) {
52 std::unique_ptr<int64_t[]> temp_timestamps;
53 if (received_ts == nullptr) {
54 temp_timestamps.reset(new int64_t[length]);
55 GenerateReceiveTimestamps(received_seq, length, temp_timestamps.get());
56 received_ts = temp_timestamps.get();
57 }
58
59 expected_seq_.clear();
60 expected_deltas_.clear();
61 feedback_.reset(new TransportFeedback(include_timestamps_));
62 feedback_->SetBase(received_seq[0], received_ts[0]);
63 ASSERT_TRUE(feedback_->IsConsistent());
64
65 int64_t last_time = feedback_->GetBaseTimeUs();
66 for (int i = 0; i < length; ++i) {
67 int64_t time = received_ts[i];
68 EXPECT_TRUE(feedback_->AddReceivedPacket(received_seq[i], time));
69
70 if (last_time != -1) {
71 int64_t delta = time - last_time;
72 expected_deltas_.push_back(delta);
73 }
74 last_time = time;
75 }
76 ASSERT_TRUE(feedback_->IsConsistent());
77 expected_seq_.insert(expected_seq_.begin(), &received_seq[0],
78 &received_seq[length]);
79 }
80
VerifyPacket()81 void VerifyPacket() {
82 ASSERT_TRUE(feedback_->IsConsistent());
83 serialized_ = feedback_->Build();
84 VerifyInternal();
85 feedback_ =
86 TransportFeedback::ParseFrom(serialized_.data(), serialized_.size());
87 ASSERT_NE(nullptr, feedback_);
88 ASSERT_TRUE(feedback_->IsConsistent());
89 EXPECT_EQ(include_timestamps_, feedback_->IncludeTimestamps());
90 VerifyInternal();
91 }
92
93 static const size_t kAnySize = static_cast<size_t>(0) - 1;
94
95 private:
VerifyInternal()96 void VerifyInternal() {
97 if (expected_size_ != kAnySize) {
98 // Round up to whole 32-bit words.
99 size_t expected_size_words = (expected_size_ + 3) / 4;
100 size_t expected_size_bytes = expected_size_words * 4;
101 EXPECT_EQ(expected_size_bytes, serialized_.size());
102 }
103
104 std::vector<uint16_t> actual_seq_nos;
105 std::vector<int64_t> actual_deltas_us;
106 for (const auto& packet : feedback_->GetReceivedPackets()) {
107 actual_seq_nos.push_back(packet.sequence_number());
108 actual_deltas_us.push_back(packet.delta_us());
109 }
110 EXPECT_THAT(actual_seq_nos, ElementsAreArray(expected_seq_));
111 if (include_timestamps_) {
112 EXPECT_THAT(actual_deltas_us, ElementsAreArray(expected_deltas_));
113 }
114 }
115
GenerateReceiveTimestamps(const uint16_t seq[],const size_t length,int64_t * timestamps)116 void GenerateReceiveTimestamps(const uint16_t seq[],
117 const size_t length,
118 int64_t* timestamps) {
119 uint16_t last_seq = seq[0];
120 int64_t offset = 0;
121
122 for (size_t i = 0; i < length; ++i) {
123 if (seq[i] < last_seq)
124 offset += 0x10000 * default_delta_;
125 last_seq = seq[i];
126
127 timestamps[i] = offset + (last_seq * default_delta_);
128 }
129 }
130
131 std::vector<uint16_t> expected_seq_;
132 std::vector<int64_t> expected_deltas_;
133 size_t expected_size_;
134 int64_t default_delta_;
135 std::unique_ptr<TransportFeedback> feedback_;
136 rtc::Buffer serialized_;
137 bool include_timestamps_;
138 };
139
140 // The following tests use FeedbackTester that simulates received packets as
141 // specified by the parameters |received_seq[]| and |received_ts[]| (optional).
142 // The following is verified in these tests:
143 // - Expected size of serialized packet.
144 // - Expected sequence numbers and receive deltas.
145 // - Sequence numbers and receive deltas are persistent after serialization
146 // followed by parsing.
147 // - The internal state of a feedback packet is consistent.
TEST(RtcpPacketTest,TransportFeedbackOneBitVector)148 TEST(RtcpPacketTest, TransportFeedbackOneBitVector) {
149 const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13};
150 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
151 const size_t kExpectedSizeBytes =
152 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
153
154 FeedbackTester test;
155 test.WithExpectedSize(kExpectedSizeBytes);
156 test.WithInput(kReceived, nullptr, kLength);
157 test.VerifyPacket();
158 }
159
TEST(RtcpPacketTest,TransportFeedbackOneBitVectorNoRecvDelta)160 TEST(RtcpPacketTest, TransportFeedbackOneBitVectorNoRecvDelta) {
161 const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13};
162 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
163 const size_t kExpectedSizeBytes = kHeaderSize + kStatusChunkSize;
164
165 FeedbackTester test(/*include_timestamps=*/false);
166 test.WithExpectedSize(kExpectedSizeBytes);
167 test.WithInput(kReceived, nullptr, kLength);
168 test.VerifyPacket();
169 }
170
TEST(RtcpPacketTest,TransportFeedbackFullOneBitVector)171 TEST(RtcpPacketTest, TransportFeedbackFullOneBitVector) {
172 const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13, 14};
173 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
174 const size_t kExpectedSizeBytes =
175 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
176
177 FeedbackTester test;
178 test.WithExpectedSize(kExpectedSizeBytes);
179 test.WithInput(kReceived, nullptr, kLength);
180 test.VerifyPacket();
181 }
182
TEST(RtcpPacketTest,TransportFeedbackOneBitVectorWrapReceived)183 TEST(RtcpPacketTest, TransportFeedbackOneBitVectorWrapReceived) {
184 const uint16_t kMax = 0xFFFF;
185 const uint16_t kReceived[] = {kMax - 2, kMax - 1, kMax, 0, 1, 2};
186 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
187 const size_t kExpectedSizeBytes =
188 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
189
190 FeedbackTester test;
191 test.WithExpectedSize(kExpectedSizeBytes);
192 test.WithInput(kReceived, nullptr, kLength);
193 test.VerifyPacket();
194 }
195
TEST(RtcpPacketTest,TransportFeedbackOneBitVectorWrapMissing)196 TEST(RtcpPacketTest, TransportFeedbackOneBitVectorWrapMissing) {
197 const uint16_t kMax = 0xFFFF;
198 const uint16_t kReceived[] = {kMax - 2, kMax - 1, 1, 2};
199 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
200 const size_t kExpectedSizeBytes =
201 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
202
203 FeedbackTester test;
204 test.WithExpectedSize(kExpectedSizeBytes);
205 test.WithInput(kReceived, nullptr, kLength);
206 test.VerifyPacket();
207 }
208
TEST(RtcpPacketTest,TransportFeedbackTwoBitVector)209 TEST(RtcpPacketTest, TransportFeedbackTwoBitVector) {
210 const uint16_t kReceived[] = {1, 2, 6, 7};
211 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
212 const size_t kExpectedSizeBytes =
213 kHeaderSize + kStatusChunkSize + (kLength * kLargeDeltaSize);
214
215 FeedbackTester test;
216 test.WithExpectedSize(kExpectedSizeBytes);
217 test.WithDefaultDelta(kDeltaLimit + TransportFeedback::kDeltaScaleFactor);
218 test.WithInput(kReceived, nullptr, kLength);
219 test.VerifyPacket();
220 }
221
TEST(RtcpPacketTest,TransportFeedbackTwoBitVectorFull)222 TEST(RtcpPacketTest, TransportFeedbackTwoBitVectorFull) {
223 const uint16_t kReceived[] = {1, 2, 6, 7, 8};
224 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
225 const size_t kExpectedSizeBytes =
226 kHeaderSize + (2 * kStatusChunkSize) + (kLength * kLargeDeltaSize);
227
228 FeedbackTester test;
229 test.WithExpectedSize(kExpectedSizeBytes);
230 test.WithDefaultDelta(kDeltaLimit + TransportFeedback::kDeltaScaleFactor);
231 test.WithInput(kReceived, nullptr, kLength);
232 test.VerifyPacket();
233 }
234
TEST(RtcpPacketTest,TransportFeedbackLargeAndNegativeDeltas)235 TEST(RtcpPacketTest, TransportFeedbackLargeAndNegativeDeltas) {
236 const uint16_t kReceived[] = {1, 2, 6, 7, 8};
237 const int64_t kReceiveTimes[] = {
238 2000, 1000, 4000, 3000,
239 3000 + TransportFeedback::kDeltaScaleFactor * (1 << 8)};
240 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
241 const size_t kExpectedSizeBytes =
242 kHeaderSize + kStatusChunkSize + (3 * kLargeDeltaSize) + kSmallDeltaSize;
243
244 FeedbackTester test;
245 test.WithExpectedSize(kExpectedSizeBytes);
246 test.WithInput(kReceived, kReceiveTimes, kLength);
247 test.VerifyPacket();
248 }
249
TEST(RtcpPacketTest,TransportFeedbackMaxRle)250 TEST(RtcpPacketTest, TransportFeedbackMaxRle) {
251 // Expected chunks created:
252 // * 1-bit vector chunk (1xreceived + 13xdropped)
253 // * RLE chunk of max length for dropped symbol
254 // * 1-bit vector chunk (1xreceived + 13xdropped)
255
256 const size_t kPacketCount = (1 << 13) - 1 + 14;
257 const uint16_t kReceived[] = {0, kPacketCount};
258 const int64_t kReceiveTimes[] = {1000, 2000};
259 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
260 const size_t kExpectedSizeBytes =
261 kHeaderSize + (3 * kStatusChunkSize) + (kLength * kSmallDeltaSize);
262
263 FeedbackTester test;
264 test.WithExpectedSize(kExpectedSizeBytes);
265 test.WithInput(kReceived, kReceiveTimes, kLength);
266 test.VerifyPacket();
267 }
268
TEST(RtcpPacketTest,TransportFeedbackMinRle)269 TEST(RtcpPacketTest, TransportFeedbackMinRle) {
270 // Expected chunks created:
271 // * 1-bit vector chunk (1xreceived + 13xdropped)
272 // * RLE chunk of length 15 for dropped symbol
273 // * 1-bit vector chunk (1xreceived + 13xdropped)
274
275 const uint16_t kReceived[] = {0, (14 * 2) + 1};
276 const int64_t kReceiveTimes[] = {1000, 2000};
277 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
278 const size_t kExpectedSizeBytes =
279 kHeaderSize + (3 * kStatusChunkSize) + (kLength * kSmallDeltaSize);
280
281 FeedbackTester test;
282 test.WithExpectedSize(kExpectedSizeBytes);
283 test.WithInput(kReceived, kReceiveTimes, kLength);
284 test.VerifyPacket();
285 }
286
TEST(RtcpPacketTest,TransportFeedbackOneToTwoBitVector)287 TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVector) {
288 const size_t kTwoBitVectorCapacity = 7;
289 const uint16_t kReceived[] = {0, kTwoBitVectorCapacity - 1};
290 const int64_t kReceiveTimes[] = {
291 0, kDeltaLimit + TransportFeedback::kDeltaScaleFactor};
292 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
293 const size_t kExpectedSizeBytes =
294 kHeaderSize + kStatusChunkSize + kSmallDeltaSize + kLargeDeltaSize;
295
296 FeedbackTester test;
297 test.WithExpectedSize(kExpectedSizeBytes);
298 test.WithInput(kReceived, kReceiveTimes, kLength);
299 test.VerifyPacket();
300 }
301
TEST(RtcpPacketTest,TransportFeedbackOneToTwoBitVectorSimpleSplit)302 TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVectorSimpleSplit) {
303 const size_t kTwoBitVectorCapacity = 7;
304 const uint16_t kReceived[] = {0, kTwoBitVectorCapacity};
305 const int64_t kReceiveTimes[] = {
306 0, kDeltaLimit + TransportFeedback::kDeltaScaleFactor};
307 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
308 const size_t kExpectedSizeBytes =
309 kHeaderSize + (kStatusChunkSize * 2) + kSmallDeltaSize + kLargeDeltaSize;
310
311 FeedbackTester test;
312 test.WithExpectedSize(kExpectedSizeBytes);
313 test.WithInput(kReceived, kReceiveTimes, kLength);
314 test.VerifyPacket();
315 }
316
TEST(RtcpPacketTest,TransportFeedbackOneToTwoBitVectorSplit)317 TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVectorSplit) {
318 // With received small delta = S, received large delta = L, use input
319 // SSSSSSSSLSSSSSSSSSSSS. This will cause a 1:2 split at the L.
320 // After split there will be two symbols in symbol_vec: SL.
321
322 const int64_t kLargeDelta = TransportFeedback::kDeltaScaleFactor * (1 << 8);
323 const size_t kNumPackets = (3 * 7) + 1;
324 const size_t kExpectedSizeBytes = kHeaderSize + (kStatusChunkSize * 3) +
325 (kSmallDeltaSize * (kNumPackets - 1)) +
326 (kLargeDeltaSize * 1);
327
328 uint16_t kReceived[kNumPackets];
329 for (size_t i = 0; i < kNumPackets; ++i)
330 kReceived[i] = i;
331
332 int64_t kReceiveTimes[kNumPackets];
333 kReceiveTimes[0] = 1000;
334 for (size_t i = 1; i < kNumPackets; ++i) {
335 int delta = (i == 8) ? kLargeDelta : 1000;
336 kReceiveTimes[i] = kReceiveTimes[i - 1] + delta;
337 }
338
339 FeedbackTester test;
340 test.WithExpectedSize(kExpectedSizeBytes);
341 test.WithInput(kReceived, kReceiveTimes, kNumPackets);
342 test.VerifyPacket();
343 }
344
TEST(RtcpPacketTest,TransportFeedbackAliasing)345 TEST(RtcpPacketTest, TransportFeedbackAliasing) {
346 TransportFeedback feedback;
347 feedback.SetBase(0, 0);
348
349 const int kSamples = 100;
350 const int64_t kTooSmallDelta = TransportFeedback::kDeltaScaleFactor / 3;
351
352 for (int i = 0; i < kSamples; ++i)
353 feedback.AddReceivedPacket(i, i * kTooSmallDelta);
354
355 feedback.Build();
356
357 int64_t accumulated_delta = 0;
358 int num_samples = 0;
359 for (const auto& packet : feedback.GetReceivedPackets()) {
360 accumulated_delta += packet.delta_us();
361 int64_t expected_time = num_samples * kTooSmallDelta;
362 ++num_samples;
363
364 EXPECT_NEAR(expected_time, accumulated_delta,
365 TransportFeedback::kDeltaScaleFactor / 2);
366 }
367 }
368
TEST(RtcpPacketTest,TransportFeedbackLimits)369 TEST(RtcpPacketTest, TransportFeedbackLimits) {
370 // Sequence number wrap above 0x8000.
371 std::unique_ptr<TransportFeedback> packet(new TransportFeedback());
372 packet->SetBase(0, 0);
373 EXPECT_TRUE(packet->AddReceivedPacket(0x0, 0));
374 EXPECT_TRUE(packet->AddReceivedPacket(0x8000, 1000));
375
376 packet.reset(new TransportFeedback());
377 packet->SetBase(0, 0);
378 EXPECT_TRUE(packet->AddReceivedPacket(0x0, 0));
379 EXPECT_FALSE(packet->AddReceivedPacket(0x8000 + 1, 1000));
380
381 // Packet status count max 0xFFFF.
382 packet.reset(new TransportFeedback());
383 packet->SetBase(0, 0);
384 EXPECT_TRUE(packet->AddReceivedPacket(0x0, 0));
385 EXPECT_TRUE(packet->AddReceivedPacket(0x8000, 1000));
386 EXPECT_TRUE(packet->AddReceivedPacket(0xFFFE, 2000));
387 EXPECT_FALSE(packet->AddReceivedPacket(0xFFFF, 3000));
388
389 // Too large delta.
390 packet.reset(new TransportFeedback());
391 packet->SetBase(0, 0);
392 int64_t kMaxPositiveTimeDelta = std::numeric_limits<int16_t>::max() *
393 TransportFeedback::kDeltaScaleFactor;
394 EXPECT_FALSE(packet->AddReceivedPacket(
395 1, kMaxPositiveTimeDelta + TransportFeedback::kDeltaScaleFactor));
396 EXPECT_TRUE(packet->AddReceivedPacket(1, kMaxPositiveTimeDelta));
397
398 // Too large negative delta.
399 packet.reset(new TransportFeedback());
400 packet->SetBase(0, 0);
401 int64_t kMaxNegativeTimeDelta = std::numeric_limits<int16_t>::min() *
402 TransportFeedback::kDeltaScaleFactor;
403 EXPECT_FALSE(packet->AddReceivedPacket(
404 1, kMaxNegativeTimeDelta - TransportFeedback::kDeltaScaleFactor));
405 EXPECT_TRUE(packet->AddReceivedPacket(1, kMaxNegativeTimeDelta));
406
407 // Base time at maximum value.
408 int64_t kMaxBaseTime =
409 static_cast<int64_t>(TransportFeedback::kDeltaScaleFactor) * (1L << 8) *
410 ((1L << 23) - 1);
411 packet.reset(new TransportFeedback());
412 packet->SetBase(0, kMaxBaseTime);
413 EXPECT_TRUE(packet->AddReceivedPacket(0, kMaxBaseTime));
414 // Serialize and de-serialize (verify 24bit parsing).
415 rtc::Buffer raw_packet = packet->Build();
416 packet = TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
417 EXPECT_EQ(kMaxBaseTime, packet->GetBaseTimeUs());
418
419 // Base time above maximum value.
420 int64_t kTooLargeBaseTime =
421 kMaxBaseTime + (TransportFeedback::kDeltaScaleFactor * (1L << 8));
422 packet.reset(new TransportFeedback());
423 packet->SetBase(0, kTooLargeBaseTime);
424 packet->AddReceivedPacket(0, kTooLargeBaseTime);
425 raw_packet = packet->Build();
426 packet = TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
427 EXPECT_NE(kTooLargeBaseTime, packet->GetBaseTimeUs());
428
429 // TODO(sprang): Once we support max length lower than RTCP length limit,
430 // add back test for max size in bytes.
431 }
432
TEST(RtcpPacketTest,TransportFeedbackPadding)433 TEST(RtcpPacketTest, TransportFeedbackPadding) {
434 const size_t kExpectedSizeBytes =
435 kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
436 const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
437 const size_t kExpectedPaddingSizeBytes =
438 4 * kExpectedSizeWords - kExpectedSizeBytes;
439
440 TransportFeedback feedback;
441 feedback.SetBase(0, 0);
442 EXPECT_TRUE(feedback.AddReceivedPacket(0, 0));
443
444 rtc::Buffer packet = feedback.Build();
445 EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
446 ASSERT_GT(kExpectedSizeWords * 4, kExpectedSizeBytes);
447 for (size_t i = kExpectedSizeBytes; i < (kExpectedSizeWords * 4 - 1); ++i)
448 EXPECT_EQ(0u, packet[i]);
449
450 EXPECT_EQ(kExpectedPaddingSizeBytes, packet[kExpectedSizeWords * 4 - 1]);
451
452 // Modify packet by adding 4 bytes of padding at the end. Not currently used
453 // when we're sending, but need to be able to handle it when receiving.
454
455 const int kPaddingBytes = 4;
456 const size_t kExpectedSizeWithPadding =
457 (kExpectedSizeWords * 4) + kPaddingBytes;
458 uint8_t mod_buffer[kExpectedSizeWithPadding];
459 memcpy(mod_buffer, packet.data(), kExpectedSizeWords * 4);
460 memset(&mod_buffer[kExpectedSizeWords * 4], 0, kPaddingBytes - 1);
461 mod_buffer[kExpectedSizeWithPadding - 1] =
462 kPaddingBytes + kExpectedPaddingSizeBytes;
463 const uint8_t padding_flag = 1 << 5;
464 mod_buffer[0] |= padding_flag;
465 ByteWriter<uint16_t>::WriteBigEndian(
466 &mod_buffer[2], ByteReader<uint16_t>::ReadBigEndian(&mod_buffer[2]) +
467 ((kPaddingBytes + 3) / 4));
468
469 std::unique_ptr<TransportFeedback> parsed_packet(
470 TransportFeedback::ParseFrom(mod_buffer, kExpectedSizeWithPadding));
471 ASSERT_TRUE(parsed_packet != nullptr);
472 EXPECT_EQ(kExpectedSizeWords * 4, packet.size()); // Padding not included.
473 }
474
TEST(RtcpPacketTest,TransportFeedbackPaddingBackwardsCompatibility)475 TEST(RtcpPacketTest, TransportFeedbackPaddingBackwardsCompatibility) {
476 const size_t kExpectedSizeBytes =
477 kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
478 const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
479 const size_t kExpectedPaddingSizeBytes =
480 4 * kExpectedSizeWords - kExpectedSizeBytes;
481
482 TransportFeedback feedback;
483 feedback.SetBase(0, 0);
484 EXPECT_TRUE(feedback.AddReceivedPacket(0, 0));
485
486 rtc::Buffer packet = feedback.Build();
487 EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
488 ASSERT_GT(kExpectedSizeWords * 4, kExpectedSizeBytes);
489 for (size_t i = kExpectedSizeBytes; i < (kExpectedSizeWords * 4 - 1); ++i)
490 EXPECT_EQ(0u, packet[i]);
491
492 EXPECT_GT(kExpectedPaddingSizeBytes, 0u);
493 EXPECT_EQ(kExpectedPaddingSizeBytes, packet[kExpectedSizeWords * 4 - 1]);
494
495 // Modify packet by removing padding bit and writing zero at the last padding
496 // byte to verify that we can parse packets from old clients, where zero
497 // padding of up to three bytes was used without the padding bit being set.
498 uint8_t mod_buffer[kExpectedSizeWords * 4];
499 memcpy(mod_buffer, packet.data(), kExpectedSizeWords * 4);
500 mod_buffer[kExpectedSizeWords * 4 - 1] = 0;
501 const uint8_t padding_flag = 1 << 5;
502 mod_buffer[0] &= ~padding_flag; // Unset padding flag.
503
504 std::unique_ptr<TransportFeedback> parsed_packet(
505 TransportFeedback::ParseFrom(mod_buffer, kExpectedSizeWords * 4));
506 ASSERT_TRUE(parsed_packet != nullptr);
507 EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
508 }
509
TEST(RtcpPacketTest,TransportFeedbackCorrectlySplitsVectorChunks)510 TEST(RtcpPacketTest, TransportFeedbackCorrectlySplitsVectorChunks) {
511 const int kOneBitVectorCapacity = 14;
512 const int64_t kLargeTimeDelta =
513 TransportFeedback::kDeltaScaleFactor * (1 << 8);
514
515 // Test that a number of small deltas followed by a large delta results in a
516 // correct split into multiple chunks, as needed.
517
518 for (int deltas = 0; deltas <= kOneBitVectorCapacity + 1; ++deltas) {
519 TransportFeedback feedback;
520 feedback.SetBase(0, 0);
521 for (int i = 0; i < deltas; ++i)
522 feedback.AddReceivedPacket(i, i * 1000);
523 feedback.AddReceivedPacket(deltas, deltas * 1000 + kLargeTimeDelta);
524
525 rtc::Buffer serialized_packet = feedback.Build();
526 std::unique_ptr<TransportFeedback> deserialized_packet =
527 TransportFeedback::ParseFrom(serialized_packet.data(),
528 serialized_packet.size());
529 EXPECT_TRUE(deserialized_packet != nullptr);
530 }
531 }
532
TEST(RtcpPacketTest,TransportFeedbackMoveConstructor)533 TEST(RtcpPacketTest, TransportFeedbackMoveConstructor) {
534 const int kSamples = 100;
535 const int64_t kDelta = TransportFeedback::kDeltaScaleFactor;
536 const uint16_t kBaseSeqNo = 7531;
537 const int64_t kBaseTimestampUs = 123456789;
538 const uint8_t kFeedbackSeqNo = 90;
539
540 TransportFeedback feedback;
541 feedback.SetBase(kBaseSeqNo, kBaseTimestampUs);
542 feedback.SetFeedbackSequenceNumber(kFeedbackSeqNo);
543 for (int i = 0; i < kSamples; ++i) {
544 feedback.AddReceivedPacket(kBaseSeqNo + i, kBaseTimestampUs + i * kDelta);
545 }
546 EXPECT_TRUE(feedback.IsConsistent());
547
548 TransportFeedback feedback_copy(feedback);
549 EXPECT_TRUE(feedback_copy.IsConsistent());
550 EXPECT_TRUE(feedback.IsConsistent());
551 EXPECT_EQ(feedback_copy.Build(), feedback.Build());
552
553 TransportFeedback moved(std::move(feedback));
554 EXPECT_TRUE(moved.IsConsistent());
555 EXPECT_TRUE(feedback.IsConsistent());
556 EXPECT_EQ(moved.Build(), feedback_copy.Build());
557 }
558
TEST(TransportFeedbackTest,ReportsMissingPackets)559 TEST(TransportFeedbackTest, ReportsMissingPackets) {
560 const uint16_t kBaseSeqNo = 1000;
561 const int64_t kBaseTimestampUs = 10000;
562 const uint8_t kFeedbackSeqNo = 90;
563 TransportFeedback feedback_builder(/*include_timestamps*/ true);
564 feedback_builder.SetBase(kBaseSeqNo, kBaseTimestampUs);
565 feedback_builder.SetFeedbackSequenceNumber(kFeedbackSeqNo);
566 feedback_builder.AddReceivedPacket(kBaseSeqNo + 0, kBaseTimestampUs);
567 // Packet losses indicated by jump in sequence number.
568 feedback_builder.AddReceivedPacket(kBaseSeqNo + 3, kBaseTimestampUs + 2000);
569 rtc::Buffer coded = feedback_builder.Build();
570
571 rtcp::CommonHeader header;
572 header.Parse(coded.data(), coded.size());
573 TransportFeedback feedback(/*include_timestamps*/ true,
574 /*include_lost*/ true);
575 feedback.Parse(header);
576 auto packets = feedback.GetAllPackets();
577 EXPECT_TRUE(packets[0].received());
578 EXPECT_FALSE(packets[1].received());
579 EXPECT_FALSE(packets[2].received());
580 EXPECT_TRUE(packets[3].received());
581 }
582
TEST(TransportFeedbackTest,ReportsMissingPacketsWithoutTimestamps)583 TEST(TransportFeedbackTest, ReportsMissingPacketsWithoutTimestamps) {
584 const uint16_t kBaseSeqNo = 1000;
585 const uint8_t kFeedbackSeqNo = 90;
586 TransportFeedback feedback_builder(/*include_timestamps*/ false);
587 feedback_builder.SetBase(kBaseSeqNo, 10000);
588 feedback_builder.SetFeedbackSequenceNumber(kFeedbackSeqNo);
589 feedback_builder.AddReceivedPacket(kBaseSeqNo + 0, /*timestamp_us*/ 0);
590 // Packet losses indicated by jump in sequence number.
591 feedback_builder.AddReceivedPacket(kBaseSeqNo + 3, /*timestamp_us*/ 0);
592 rtc::Buffer coded = feedback_builder.Build();
593
594 rtcp::CommonHeader header;
595 header.Parse(coded.data(), coded.size());
596 TransportFeedback feedback(/*include_timestamps*/ true,
597 /*include_lost*/ true);
598 feedback.Parse(header);
599 auto packets = feedback.GetAllPackets();
600 EXPECT_TRUE(packets[0].received());
601 EXPECT_FALSE(packets[1].received());
602 EXPECT_FALSE(packets[2].received());
603 EXPECT_TRUE(packets[3].received());
604 }
605 } // namespace
606 } // namespace webrtc
607