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