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 <algorithm>
14 
15 #include "modules/include/module_common_types.h"
16 #include "modules/rtp_rtcp/source/byte_io.h"
17 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/logging.h"
20 #include "rtc_base/trace_event.h"
21 
22 namespace webrtc {
23 namespace rtcp {
24 namespace {
25 // Header size:
26 // * 4 bytes Common RTCP Packet Header
27 // * 8 bytes Common Packet Format for RTCP Feedback Messages
28 // * 8 bytes FeedbackPacket header
29 constexpr size_t kTransportFeedbackHeaderSizeBytes = 4 + 8 + 8;
30 constexpr size_t kChunkSizeBytes = 2;
31 // TODO(sprang): Add support for dynamic max size for easier fragmentation,
32 // eg. set it to what's left in the buffer or IP_PACKET_SIZE.
33 // Size constraint imposed by RTCP common header: 16bit size field interpreted
34 // as number of four byte words minus the first header word.
35 constexpr size_t kMaxSizeBytes = (1 << 16) * 4;
36 // Payload size:
37 // * 8 bytes Common Packet Format for RTCP Feedback Messages
38 // * 8 bytes FeedbackPacket header.
39 // * 2 bytes for one chunk.
40 constexpr size_t kMinPayloadSizeBytes = 8 + 8 + 2;
41 constexpr int kBaseScaleFactor =
42     TransportFeedback::kDeltaScaleFactor * (1 << 8);
43 constexpr int64_t kTimeWrapPeriodUs = (1ll << 24) * kBaseScaleFactor;
44 
45 //    Message format
46 //
47 //     0                   1                   2                   3
48 //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
49 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 //    |V=2|P|  FMT=15 |    PT=205     |           length              |
51 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 //  0 |                     SSRC of packet sender                     |
53 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 //  4 |                      SSRC of media source                     |
55 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 //  8 |      base sequence number     |      packet status count      |
57 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 // 12 |                 reference time                | fb pkt. count |
59 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 // 16 |          packet chunk         |         packet chunk          |
61 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 //    .                                                               .
63 //    .                                                               .
64 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 //    |         packet chunk          |  recv delta   |  recv delta   |
66 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67 //    .                                                               .
68 //    .                                                               .
69 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 //    |           recv delta          |  recv delta   | zero padding  |
71 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 }  // namespace
73 constexpr uint8_t TransportFeedback::kFeedbackMessageType;
74 constexpr size_t TransportFeedback::kMaxReportedPackets;
75 
76 // Keep delta_sizes that can be encoded into single chunk if it is last chunk.
77 class TransportFeedback::LastChunk {
78  public:
79   using DeltaSize = TransportFeedback::DeltaSize;
80 
81   LastChunk();
82 
83   bool Empty() const;
84   void Clear();
85   // Return if delta sizes still can be encoded into single chunk with added
86   // |delta_size|.
87   bool CanAdd(DeltaSize delta_size) const;
88   // Add |delta_size|, assumes |CanAdd(delta_size)|,
89   void Add(DeltaSize delta_size);
90 
91   // Encode chunk as large as possible removing encoded delta sizes.
92   // Assume CanAdd() == false for some valid delta_size.
93   uint16_t Emit();
94   // Encode all stored delta_sizes into single chunk, pad with 0s if needed.
95   uint16_t EncodeLast() const;
96 
97   // Decode up to |max_size| delta sizes from |chunk|.
98   void Decode(uint16_t chunk, size_t max_size);
99   // Appends content of the Lastchunk to |deltas|.
100   void AppendTo(std::vector<DeltaSize>* deltas) const;
101 
102  private:
103   static constexpr size_t kMaxRunLengthCapacity = 0x1fff;
104   static constexpr size_t kMaxOneBitCapacity = 14;
105   static constexpr size_t kMaxTwoBitCapacity = 7;
106   static constexpr size_t kMaxVectorCapacity = kMaxOneBitCapacity;
107   static constexpr DeltaSize kLarge = 2;
108 
109   uint16_t EncodeOneBit() const;
110   void DecodeOneBit(uint16_t chunk, size_t max_size);
111 
112   uint16_t EncodeTwoBit(size_t size) const;
113   void DecodeTwoBit(uint16_t chunk, size_t max_size);
114 
115   uint16_t EncodeRunLength() const;
116   void DecodeRunLength(uint16_t chunk, size_t max_size);
117 
118   DeltaSize delta_sizes_[kMaxVectorCapacity];
119   size_t size_;
120   bool all_same_;
121   bool has_large_delta_;
122 };
123 constexpr size_t TransportFeedback::LastChunk::kMaxRunLengthCapacity;
124 constexpr size_t TransportFeedback::LastChunk::kMaxOneBitCapacity;
125 constexpr size_t TransportFeedback::LastChunk::kMaxTwoBitCapacity;
126 constexpr size_t TransportFeedback::LastChunk::kMaxVectorCapacity;
127 
LastChunk()128 TransportFeedback::LastChunk::LastChunk() {
129   Clear();
130 }
131 
Empty() const132 bool TransportFeedback::LastChunk::Empty() const {
133   return size_ == 0;
134 }
135 
Clear()136 void TransportFeedback::LastChunk::Clear() {
137   size_ = 0;
138   all_same_ = true;
139   has_large_delta_ = false;
140 }
141 
CanAdd(DeltaSize delta_size) const142 bool TransportFeedback::LastChunk::CanAdd(DeltaSize delta_size) const {
143   RTC_DCHECK_LE(delta_size, 2);
144   if (size_ < kMaxTwoBitCapacity)
145     return true;
146   if (size_ < kMaxOneBitCapacity && !has_large_delta_ && delta_size != kLarge)
147     return true;
148   if (size_ < kMaxRunLengthCapacity && all_same_ &&
149       delta_sizes_[0] == delta_size)
150     return true;
151   return false;
152 }
153 
Add(DeltaSize delta_size)154 void TransportFeedback::LastChunk::Add(DeltaSize delta_size) {
155   RTC_DCHECK(CanAdd(delta_size));
156   if (size_ < kMaxVectorCapacity)
157     delta_sizes_[size_] = delta_size;
158   size_++;
159   all_same_ = all_same_ && delta_size == delta_sizes_[0];
160   has_large_delta_ = has_large_delta_ || delta_size == kLarge;
161 }
162 
Emit()163 uint16_t TransportFeedback::LastChunk::Emit() {
164   RTC_DCHECK(!CanAdd(0) || !CanAdd(1) || !CanAdd(2));
165   if (all_same_) {
166     uint16_t chunk = EncodeRunLength();
167     Clear();
168     return chunk;
169   }
170   if (size_ == kMaxOneBitCapacity) {
171     uint16_t chunk = EncodeOneBit();
172     Clear();
173     return chunk;
174   }
175   RTC_DCHECK_GE(size_, kMaxTwoBitCapacity);
176   uint16_t chunk = EncodeTwoBit(kMaxTwoBitCapacity);
177   // Remove |kMaxTwoBitCapacity| encoded delta sizes:
178   // Shift remaining delta sizes and recalculate all_same_ && has_large_delta_.
179   size_ -= kMaxTwoBitCapacity;
180   all_same_ = true;
181   has_large_delta_ = false;
182   for (size_t i = 0; i < size_; ++i) {
183     DeltaSize delta_size = delta_sizes_[kMaxTwoBitCapacity + i];
184     delta_sizes_[i] = delta_size;
185     all_same_ = all_same_ && delta_size == delta_sizes_[0];
186     has_large_delta_ = has_large_delta_ || delta_size == kLarge;
187   }
188 
189   return chunk;
190 }
191 
EncodeLast() const192 uint16_t TransportFeedback::LastChunk::EncodeLast() const {
193   RTC_DCHECK_GT(size_, 0);
194   if (all_same_)
195     return EncodeRunLength();
196   if (size_ <= kMaxTwoBitCapacity)
197     return EncodeTwoBit(size_);
198   return EncodeOneBit();
199 }
200 
201 // Appends content of the Lastchunk to |deltas|.
AppendTo(std::vector<DeltaSize> * deltas) const202 void TransportFeedback::LastChunk::AppendTo(
203     std::vector<DeltaSize>* deltas) const {
204   if (all_same_) {
205     deltas->insert(deltas->end(), size_, delta_sizes_[0]);
206   } else {
207     deltas->insert(deltas->end(), delta_sizes_, delta_sizes_ + size_);
208   }
209 }
210 
Decode(uint16_t chunk,size_t max_size)211 void TransportFeedback::LastChunk::Decode(uint16_t chunk, size_t max_size) {
212   if ((chunk & 0x8000) == 0) {
213     DecodeRunLength(chunk, max_size);
214   } else if ((chunk & 0x4000) == 0) {
215     DecodeOneBit(chunk, max_size);
216   } else {
217     DecodeTwoBit(chunk, max_size);
218   }
219 }
220 
221 //  One Bit Status Vector Chunk
222 //
223 //  0                   1
224 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
225 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
226 //  |T|S|       symbol list         |
227 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
228 //
229 //  T = 1
230 //  S = 0
231 //  Symbol list = 14 entries where 0 = not received, 1 = received 1-byte delta.
EncodeOneBit() const232 uint16_t TransportFeedback::LastChunk::EncodeOneBit() const {
233   RTC_DCHECK(!has_large_delta_);
234   RTC_DCHECK_LE(size_, kMaxOneBitCapacity);
235   uint16_t chunk = 0x8000;
236   for (size_t i = 0; i < size_; ++i)
237     chunk |= delta_sizes_[i] << (kMaxOneBitCapacity - 1 - i);
238   return chunk;
239 }
240 
DecodeOneBit(uint16_t chunk,size_t max_size)241 void TransportFeedback::LastChunk::DecodeOneBit(uint16_t chunk,
242                                                 size_t max_size) {
243   RTC_DCHECK_EQ(chunk & 0xc000, 0x8000);
244   size_ = std::min(kMaxOneBitCapacity, max_size);
245   has_large_delta_ = false;
246   all_same_ = false;
247   for (size_t i = 0; i < size_; ++i)
248     delta_sizes_[i] = (chunk >> (kMaxOneBitCapacity - 1 - i)) & 0x01;
249 }
250 
251 //  Two Bit Status Vector Chunk
252 //
253 //  0                   1
254 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
255 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
256 //  |T|S|       symbol list         |
257 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
258 //
259 //  T = 1
260 //  S = 1
261 //  symbol list = 7 entries of two bits each.
EncodeTwoBit(size_t size) const262 uint16_t TransportFeedback::LastChunk::EncodeTwoBit(size_t size) const {
263   RTC_DCHECK_LE(size, size_);
264   uint16_t chunk = 0xc000;
265   for (size_t i = 0; i < size; ++i)
266     chunk |= delta_sizes_[i] << 2 * (kMaxTwoBitCapacity - 1 - i);
267   return chunk;
268 }
269 
DecodeTwoBit(uint16_t chunk,size_t max_size)270 void TransportFeedback::LastChunk::DecodeTwoBit(uint16_t chunk,
271                                                 size_t max_size) {
272   RTC_DCHECK_EQ(chunk & 0xc000, 0xc000);
273   size_ = std::min(kMaxTwoBitCapacity, max_size);
274   has_large_delta_ = true;
275   all_same_ = false;
276   for (size_t i = 0; i < size_; ++i)
277     delta_sizes_[i] = (chunk >> 2 * (kMaxTwoBitCapacity - 1 - i)) & 0x03;
278 }
279 
280 //  Run Length Status Vector Chunk
281 //
282 //  0                   1
283 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
284 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285 //  |T| S |       Run Length        |
286 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
287 //
288 //  T = 0
289 //  S = symbol
290 //  Run Length = Unsigned integer denoting the run length of the symbol
EncodeRunLength() const291 uint16_t TransportFeedback::LastChunk::EncodeRunLength() const {
292   RTC_DCHECK(all_same_);
293   RTC_DCHECK_LE(size_, kMaxRunLengthCapacity);
294   return (delta_sizes_[0] << 13) | static_cast<uint16_t>(size_);
295 }
296 
DecodeRunLength(uint16_t chunk,size_t max_count)297 void TransportFeedback::LastChunk::DecodeRunLength(uint16_t chunk,
298                                                    size_t max_count) {
299   RTC_DCHECK_EQ(chunk & 0x8000, 0);
300   size_ = std::min<size_t>(chunk & 0x1fff, max_count);
301   DeltaSize delta_size = (chunk >> 13) & 0x03;
302   has_large_delta_ = delta_size >= kLarge;
303   all_same_ = true;
304   // To make it consistent with Add function, populate delta_sizes_ beyound 1st.
305   for (size_t i = 0; i < std::min<size_t>(size_, kMaxVectorCapacity); ++i)
306     delta_sizes_[i] = delta_size;
307 }
308 
TransportFeedback()309 TransportFeedback::TransportFeedback()
310     : base_seq_no_(0),
311       num_seq_no_(0),
312       base_time_ticks_(0),
313       feedback_seq_(0),
314       last_timestamp_us_(0),
315       last_chunk_(new LastChunk()),
316       size_bytes_(kTransportFeedbackHeaderSizeBytes) {}
317 
~TransportFeedback()318 TransportFeedback::~TransportFeedback() {}
319 
SetBase(uint16_t base_sequence,int64_t ref_timestamp_us)320 void TransportFeedback::SetBase(uint16_t base_sequence,
321                                 int64_t ref_timestamp_us) {
322   RTC_DCHECK_EQ(num_seq_no_, 0);
323   RTC_DCHECK_GE(ref_timestamp_us, 0);
324   base_seq_no_ = base_sequence;
325   base_time_ticks_ = (ref_timestamp_us % kTimeWrapPeriodUs) / kBaseScaleFactor;
326   last_timestamp_us_ = GetBaseTimeUs();
327 }
328 
SetFeedbackSequenceNumber(uint8_t feedback_sequence)329 void TransportFeedback::SetFeedbackSequenceNumber(uint8_t feedback_sequence) {
330   feedback_seq_ = feedback_sequence;
331 }
332 
AddReceivedPacket(uint16_t sequence_number,int64_t timestamp_us)333 bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number,
334                                           int64_t timestamp_us) {
335   // Convert to ticks and round.
336   int64_t delta_full = (timestamp_us - last_timestamp_us_) % kTimeWrapPeriodUs;
337   if (delta_full > kTimeWrapPeriodUs / 2)
338     delta_full -= kTimeWrapPeriodUs;
339   delta_full +=
340       delta_full < 0 ? -(kDeltaScaleFactor / 2) : kDeltaScaleFactor / 2;
341   delta_full /= kDeltaScaleFactor;
342 
343   int16_t delta = static_cast<int16_t>(delta_full);
344   // If larger than 16bit signed, we can't represent it - need new fb packet.
345   if (delta != delta_full) {
346     RTC_LOG(LS_WARNING) << "Delta value too large ( >= 2^16 ticks )";
347     return false;
348   }
349 
350   uint16_t next_seq_no = base_seq_no_ + num_seq_no_;
351   if (sequence_number != next_seq_no) {
352     uint16_t last_seq_no = next_seq_no - 1;
353     if (!IsNewerSequenceNumber(sequence_number, last_seq_no))
354       return false;
355     for (; next_seq_no != sequence_number; ++next_seq_no)
356       if (!AddDeltaSize(0))
357         return false;
358   }
359 
360   DeltaSize delta_size = (delta >= 0 && delta <= 0xff) ? 1 : 2;
361   if (!AddDeltaSize(delta_size))
362     return false;
363 
364   packets_.emplace_back(sequence_number, delta);
365   last_timestamp_us_ += delta * kDeltaScaleFactor;
366   size_bytes_ += delta_size;
367   return true;
368 }
369 
370 const std::vector<TransportFeedback::ReceivedPacket>&
GetReceivedPackets() const371 TransportFeedback::GetReceivedPackets() const {
372   return packets_;
373 }
374 
GetBaseSequence() const375 uint16_t TransportFeedback::GetBaseSequence() const {
376   return base_seq_no_;
377 }
378 
GetBaseTimeUs() const379 int64_t TransportFeedback::GetBaseTimeUs() const {
380   return static_cast<int64_t>(base_time_ticks_) * kBaseScaleFactor;
381 }
382 
383 // De-serialize packet.
Parse(const CommonHeader & packet)384 bool TransportFeedback::Parse(const CommonHeader& packet) {
385   RTC_DCHECK_EQ(packet.type(), kPacketType);
386   RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType);
387   TRACE_EVENT0("webrtc", "TransportFeedback::Parse");
388 
389   if (packet.payload_size_bytes() < kMinPayloadSizeBytes) {
390     RTC_LOG(LS_WARNING) << "Buffer too small (" << packet.payload_size_bytes()
391                         << " bytes) to fit a "
392                            "FeedbackPacket. Minimum size = "
393                         << kMinPayloadSizeBytes;
394     return false;
395   }
396 
397   const uint8_t* const payload = packet.payload();
398   ParseCommonFeedback(payload);
399 
400   base_seq_no_ = ByteReader<uint16_t>::ReadBigEndian(&payload[8]);
401   uint16_t status_count = ByteReader<uint16_t>::ReadBigEndian(&payload[10]);
402   base_time_ticks_ = ByteReader<int32_t, 3>::ReadBigEndian(&payload[12]);
403   feedback_seq_ = payload[15];
404   Clear();
405   size_t index = 16;
406   const size_t end_index = packet.payload_size_bytes();
407 
408   if (status_count == 0) {
409     RTC_LOG(LS_WARNING) << "Empty feedback messages not allowed.";
410     return false;
411   }
412 
413   std::vector<uint8_t> delta_sizes;
414   delta_sizes.reserve(status_count);
415   while (delta_sizes.size() < status_count) {
416     if (index + kChunkSizeBytes > end_index) {
417       RTC_LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
418       Clear();
419       return false;
420     }
421 
422     uint16_t chunk = ByteReader<uint16_t>::ReadBigEndian(&payload[index]);
423     index += kChunkSizeBytes;
424     encoded_chunks_.push_back(chunk);
425     last_chunk_->Decode(chunk, status_count - delta_sizes.size());
426     last_chunk_->AppendTo(&delta_sizes);
427   }
428   // Last chunk is stored in the |last_chunk_|.
429   encoded_chunks_.pop_back();
430   RTC_DCHECK_EQ(delta_sizes.size(), status_count);
431   num_seq_no_ = status_count;
432 
433   uint16_t seq_no = base_seq_no_;
434   for (size_t delta_size : delta_sizes) {
435     if (index + delta_size > end_index) {
436       RTC_LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
437       Clear();
438       return false;
439     }
440     switch (delta_size) {
441       case 0:
442         break;
443       case 1: {
444         int16_t delta = payload[index];
445         packets_.emplace_back(seq_no, delta);
446         last_timestamp_us_ += delta * kDeltaScaleFactor;
447         index += delta_size;
448         break;
449       }
450       case 2: {
451         int16_t delta = ByteReader<int16_t>::ReadBigEndian(&payload[index]);
452         packets_.emplace_back(seq_no, delta);
453         last_timestamp_us_ += delta * kDeltaScaleFactor;
454         index += delta_size;
455         break;
456       }
457       case 3:
458         Clear();
459         RTC_LOG(LS_WARNING) << "Invalid delta_size for seq_no " << seq_no;
460         return false;
461       default:
462         RTC_NOTREACHED();
463         break;
464     }
465     ++seq_no;
466   }
467   size_bytes_ = RtcpPacket::kHeaderLength + index;
468   RTC_DCHECK_LE(index, end_index);
469   return true;
470 }
471 
ParseFrom(const uint8_t * buffer,size_t length)472 std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
473     const uint8_t* buffer,
474     size_t length) {
475   CommonHeader header;
476   if (!header.Parse(buffer, length))
477     return nullptr;
478   if (header.type() != kPacketType || header.fmt() != kFeedbackMessageType)
479     return nullptr;
480   std::unique_ptr<TransportFeedback> parsed(new TransportFeedback);
481   if (!parsed->Parse(header))
482     return nullptr;
483   return parsed;
484 }
485 
IsConsistent() const486 bool TransportFeedback::IsConsistent() const {
487   size_t packet_size = kTransportFeedbackHeaderSizeBytes;
488   std::vector<DeltaSize> delta_sizes;
489   LastChunk chunk_decoder;
490   for (uint16_t chunk : encoded_chunks_) {
491     chunk_decoder.Decode(chunk, kMaxReportedPackets);
492     chunk_decoder.AppendTo(&delta_sizes);
493     packet_size += kChunkSizeBytes;
494   }
495   if (!last_chunk_->Empty()) {
496     last_chunk_->AppendTo(&delta_sizes);
497     packet_size += kChunkSizeBytes;
498   }
499   if (num_seq_no_ != delta_sizes.size()) {
500     RTC_LOG(LS_ERROR) << delta_sizes.size() << " packets encoded. Expected "
501                       << num_seq_no_;
502     return false;
503   }
504   int64_t timestamp_us = base_time_ticks_ * kBaseScaleFactor;
505   auto packet_it = packets_.begin();
506   uint16_t seq_no = base_seq_no_;
507   for (DeltaSize delta_size : delta_sizes) {
508     if (delta_size > 0) {
509       if (packet_it == packets_.end()) {
510         RTC_LOG(LS_ERROR) << "Failed to find delta for seq_no " << seq_no;
511         return false;
512       }
513       if (packet_it->sequence_number() != seq_no) {
514         RTC_LOG(LS_ERROR) << "Expected to find delta for seq_no " << seq_no
515                           << ". Next delta is for "
516                           << packet_it->sequence_number();
517         return false;
518       }
519       if (delta_size == 1 &&
520           (packet_it->delta_ticks() < 0 || packet_it->delta_ticks() > 0xff)) {
521         RTC_LOG(LS_ERROR) << "Delta " << packet_it->delta_ticks()
522                           << " for seq_no " << seq_no
523                           << " doesn't fit into one byte";
524         return false;
525       }
526       timestamp_us += packet_it->delta_us();
527       ++packet_it;
528     }
529     packet_size += delta_size;
530     ++seq_no;
531   }
532   if (packet_it != packets_.end()) {
533     RTC_LOG(LS_ERROR) << "Unencoded delta for seq_no "
534                       << packet_it->sequence_number();
535     return false;
536   }
537   if (timestamp_us != last_timestamp_us_) {
538     RTC_LOG(LS_ERROR) << "Last timestamp mismatch. Calculated: " << timestamp_us
539                       << ". Saved: " << last_timestamp_us_;
540     return false;
541   }
542   if (size_bytes_ != packet_size) {
543     RTC_LOG(LS_ERROR) << "Rtcp packet size mismatch. Calculated: "
544                       << packet_size << ". Saved: " << size_bytes_;
545     return false;
546   }
547   return true;
548 }
549 
BlockLength() const550 size_t TransportFeedback::BlockLength() const {
551   // Round size_bytes_ up to multiple of 32bits.
552   return (size_bytes_ + 3) & (~static_cast<size_t>(3));
553 }
554 
555 // Serialize packet.
Create(uint8_t * packet,size_t * position,size_t max_length,PacketReadyCallback * callback) const556 bool TransportFeedback::Create(uint8_t* packet,
557                                size_t* position,
558                                size_t max_length,
559                                PacketReadyCallback* callback) const {
560   if (num_seq_no_ == 0)
561     return false;
562 
563   while (*position + BlockLength() > max_length) {
564     if (!OnBufferFull(packet, position, callback))
565       return false;
566   }
567   const size_t position_end = *position + BlockLength();
568 
569   CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
570                position);
571   CreateCommonFeedback(packet + *position);
572   *position += kCommonFeedbackLength;
573 
574   ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_no_);
575   *position += 2;
576 
577   ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], num_seq_no_);
578   *position += 2;
579 
580   ByteWriter<int32_t, 3>::WriteBigEndian(&packet[*position], base_time_ticks_);
581   *position += 3;
582 
583   packet[(*position)++] = feedback_seq_;
584 
585   for (uint16_t chunk : encoded_chunks_) {
586     ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], chunk);
587     *position += 2;
588   }
589   if (!last_chunk_->Empty()) {
590     uint16_t chunk = last_chunk_->EncodeLast();
591     ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], chunk);
592     *position += 2;
593   }
594 
595   for (const auto& received_packet : packets_) {
596     int16_t delta = received_packet.delta_ticks();
597     if (delta >= 0 && delta <= 0xFF) {
598       packet[(*position)++] = delta;
599     } else {
600       ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
601       *position += 2;
602     }
603   }
604 
605   while ((*position % 4) != 0)
606     packet[(*position)++] = 0;
607 
608   RTC_DCHECK_EQ(*position, position_end);
609   return true;
610 }
611 
Clear()612 void TransportFeedback::Clear() {
613   num_seq_no_ = 0;
614   last_timestamp_us_ = GetBaseTimeUs();
615   packets_.clear();
616   encoded_chunks_.clear();
617   last_chunk_->Clear();
618   size_bytes_ = kTransportFeedbackHeaderSizeBytes;
619 }
620 
AddDeltaSize(DeltaSize delta_size)621 bool TransportFeedback::AddDeltaSize(DeltaSize delta_size) {
622   if (num_seq_no_ == kMaxReportedPackets)
623     return false;
624   size_t add_chunk_size = last_chunk_->Empty() ? kChunkSizeBytes : 0;
625   if (size_bytes_ + delta_size + add_chunk_size > kMaxSizeBytes)
626     return false;
627 
628   if (last_chunk_->CanAdd(delta_size)) {
629     size_bytes_ += add_chunk_size;
630     last_chunk_->Add(delta_size);
631     ++num_seq_no_;
632     return true;
633   }
634   if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
635     return false;
636 
637   encoded_chunks_.push_back(last_chunk_->Emit());
638   size_bytes_ += kChunkSizeBytes;
639   last_chunk_->Add(delta_size);
640   ++num_seq_no_;
641   return true;
642 }
643 
644 }  // namespace rtcp
645 }  // namespace webrtc
646