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