• 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 "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
12 
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
17 
18 namespace webrtc {
19 namespace rtcp {
20 
21 // Header size:
22 // * 12 bytes Common Packet Format for RTCP Feedback Messages
23 // * 8 bytes FeedbackPacket header
24 static const uint32_t kHeaderSizeBytes = 12 + 8;
25 static const uint32_t kChunkSizeBytes = 2;
26 static const uint32_t kOneBitVectorCapacity = 14;
27 static const uint32_t kTwoBitVectorCapacity = 7;
28 static const uint32_t kRunLengthCapacity = 0x1FFF;
29 // TODO(sprang): Add support for dynamic max size for easier fragmentation,
30 // eg. set it to what's left in the buffer or IP_PACKET_SIZE.
31 // Size constraint imposed by RTCP common header: 16bit size field interpreted
32 // as number of four byte words minus the first header word.
33 static const uint32_t kMaxSizeBytes = (1 << 16) * 4;
34 static const uint32_t kMinSizeBytes = kHeaderSizeBytes + kChunkSizeBytes;
35 static const uint32_t kBaseScaleFactor =
36     TransportFeedback::kDeltaScaleFactor * (1 << 8);
37 
38 class PacketStatusChunk {
39  public:
~PacketStatusChunk()40   virtual ~PacketStatusChunk() {}
41   virtual uint16_t NumSymbols() const = 0;
42   virtual void AppendSymbolsTo(
43       std::vector<TransportFeedback::StatusSymbol>* vec) const = 0;
44   virtual void WriteTo(uint8_t* buffer) const = 0;
45 };
46 
EncodeSymbol(TransportFeedback::StatusSymbol symbol)47 uint8_t EncodeSymbol(TransportFeedback::StatusSymbol symbol) {
48   switch (symbol) {
49     case TransportFeedback::StatusSymbol::kNotReceived:
50       return 0;
51     case TransportFeedback::StatusSymbol::kReceivedSmallDelta:
52       return 1;
53     case TransportFeedback::StatusSymbol::kReceivedLargeDelta:
54       return 2;
55     default:
56       RTC_NOTREACHED();
57       return 0;
58   }
59 }
60 
DecodeSymbol(uint8_t value)61 TransportFeedback::StatusSymbol DecodeSymbol(uint8_t value) {
62   switch (value) {
63     case 0:
64       return TransportFeedback::StatusSymbol::kNotReceived;
65     case 1:
66       return TransportFeedback::StatusSymbol::kReceivedSmallDelta;
67     case 2:
68       return TransportFeedback::StatusSymbol::kReceivedLargeDelta;
69     default:
70       RTC_NOTREACHED();
71       return TransportFeedback::StatusSymbol::kNotReceived;
72   }
73 }
74 
TransportFeedback()75 TransportFeedback::TransportFeedback()
76     : packet_sender_ssrc_(0),
77       media_source_ssrc_(0),
78       base_seq_(-1),
79       base_time_(-1),
80       feedback_seq_(0),
81       last_seq_(-1),
82       last_timestamp_(-1),
83       first_symbol_cardinality_(0),
84       vec_needs_two_bit_symbols_(false),
85       size_bytes_(kHeaderSizeBytes) {
86 }
87 
~TransportFeedback()88 TransportFeedback::~TransportFeedback() {
89   for (PacketStatusChunk* chunk : status_chunks_)
90     delete chunk;
91 }
92 
93 //  One Bit Status Vector Chunk
94 //
95 //  0                   1
96 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
97 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 //  |T|S|       symbol list         |
99 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 //
101 //  T = 1
102 //  S = 0
103 //  symbol list = 14 entries where 0 = not received, 1 = received
104 
105 class OneBitVectorChunk : public PacketStatusChunk {
106  public:
107   static const int kCapacity = 14;
108 
OneBitVectorChunk(std::deque<TransportFeedback::StatusSymbol> * symbols)109   explicit OneBitVectorChunk(
110       std::deque<TransportFeedback::StatusSymbol>* symbols) {
111     size_t input_size = symbols->size();
112     for (size_t i = 0; i < kCapacity; ++i) {
113       if (i < input_size) {
114         symbols_[i] = symbols->front();
115         symbols->pop_front();
116       } else {
117         symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived;
118       }
119     }
120   }
121 
~OneBitVectorChunk()122   virtual ~OneBitVectorChunk() {}
123 
NumSymbols() const124   uint16_t NumSymbols() const override { return kCapacity; }
125 
AppendSymbolsTo(std::vector<TransportFeedback::StatusSymbol> * vec) const126   void AppendSymbolsTo(
127       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
128     vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
129   }
130 
WriteTo(uint8_t * buffer) const131   void WriteTo(uint8_t* buffer) const override {
132     const int kSymbolsInFirstByte = 6;
133     const int kSymbolsInSecondByte = 8;
134     buffer[0] = 0x80u;
135     for (int i = 0; i < kSymbolsInFirstByte; ++i) {
136       uint8_t encoded_symbol = EncodeSymbol(symbols_[i]);
137       RTC_DCHECK_LE(encoded_symbol, 1u);
138       buffer[0] |= encoded_symbol << (kSymbolsInFirstByte - (i + 1));
139     }
140     buffer[1] = 0x00u;
141     for (int i = 0; i < kSymbolsInSecondByte; ++i) {
142       uint8_t encoded_symbol = EncodeSymbol(symbols_[i + kSymbolsInFirstByte]);
143       RTC_DCHECK_LE(encoded_symbol, 1u);
144       buffer[1] |= encoded_symbol << (kSymbolsInSecondByte - (i + 1));
145     }
146   }
147 
ParseFrom(const uint8_t * data)148   static OneBitVectorChunk* ParseFrom(const uint8_t* data) {
149     OneBitVectorChunk* chunk = new OneBitVectorChunk();
150 
151     size_t index = 0;
152     for (int i = 5; i >= 0; --i)  // Last 5 bits from first byte.
153       chunk->symbols_[index++] = DecodeSymbol((data[0] >> i) & 0x01);
154     for (int i = 7; i >= 0; --i)  // 8 bits from the last byte.
155       chunk->symbols_[index++] = DecodeSymbol((data[1] >> i) & 0x01);
156 
157     return chunk;
158   }
159 
160  private:
OneBitVectorChunk()161   OneBitVectorChunk() {}
162 
163   TransportFeedback::StatusSymbol symbols_[kCapacity];
164 };
165 
166 //  Two Bit Status Vector Chunk
167 //
168 //  0                   1
169 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
170 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 //  |T|S|       symbol list         |
172 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 //
174 //  T = 1
175 //  S = 1
176 //  symbol list = 7 entries of two bits each, see (Encode|Decode)Symbol
177 
178 class TwoBitVectorChunk : public PacketStatusChunk {
179  public:
180   static const int kCapacity = 7;
181 
TwoBitVectorChunk(std::deque<TransportFeedback::StatusSymbol> * symbols)182   explicit TwoBitVectorChunk(
183       std::deque<TransportFeedback::StatusSymbol>* symbols) {
184     size_t input_size = symbols->size();
185     for (size_t i = 0; i < kCapacity; ++i) {
186       if (i < input_size) {
187         symbols_[i] = symbols->front();
188         symbols->pop_front();
189       } else {
190         symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived;
191       }
192     }
193   }
194 
~TwoBitVectorChunk()195   virtual ~TwoBitVectorChunk() {}
196 
NumSymbols() const197   uint16_t NumSymbols() const override { return kCapacity; }
198 
AppendSymbolsTo(std::vector<TransportFeedback::StatusSymbol> * vec) const199   void AppendSymbolsTo(
200       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
201     vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
202   }
203 
WriteTo(uint8_t * buffer) const204   void WriteTo(uint8_t* buffer) const override {
205     buffer[0] = 0xC0;
206     buffer[0] |= EncodeSymbol(symbols_[0]) << 4;
207     buffer[0] |= EncodeSymbol(symbols_[1]) << 2;
208     buffer[0] |= EncodeSymbol(symbols_[2]);
209     buffer[1] = EncodeSymbol(symbols_[3]) << 6;
210     buffer[1] |= EncodeSymbol(symbols_[4]) << 4;
211     buffer[1] |= EncodeSymbol(symbols_[5]) << 2;
212     buffer[1] |= EncodeSymbol(symbols_[6]);
213   }
214 
ParseFrom(const uint8_t * buffer)215   static TwoBitVectorChunk* ParseFrom(const uint8_t* buffer) {
216     TwoBitVectorChunk* chunk = new TwoBitVectorChunk();
217 
218     chunk->symbols_[0] = DecodeSymbol((buffer[0] >> 4) & 0x03);
219     chunk->symbols_[1] = DecodeSymbol((buffer[0] >> 2) & 0x03);
220     chunk->symbols_[2] = DecodeSymbol(buffer[0] & 0x03);
221     chunk->symbols_[3] = DecodeSymbol((buffer[1] >> 6) & 0x03);
222     chunk->symbols_[4] = DecodeSymbol((buffer[1] >> 4) & 0x03);
223     chunk->symbols_[5] = DecodeSymbol((buffer[1] >> 2) & 0x03);
224     chunk->symbols_[6] = DecodeSymbol(buffer[1] & 0x03);
225 
226     return chunk;
227   }
228 
229  private:
TwoBitVectorChunk()230   TwoBitVectorChunk() {}
231 
232   TransportFeedback::StatusSymbol symbols_[kCapacity];
233 };
234 
235 //  Two Bit 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, see (Encode|Decode)Symbol
245 //  Run Length = Unsigned integer denoting the run length of the symbol
246 
247 class RunLengthChunk : public PacketStatusChunk {
248  public:
RunLengthChunk(TransportFeedback::StatusSymbol symbol,size_t size)249   RunLengthChunk(TransportFeedback::StatusSymbol symbol, size_t size)
250       : symbol_(symbol), size_(size) {
251     RTC_DCHECK_LE(size, 0x1FFFu);
252   }
253 
~RunLengthChunk()254   virtual ~RunLengthChunk() {}
255 
NumSymbols() const256   uint16_t NumSymbols() const override { return size_; }
257 
AppendSymbolsTo(std::vector<TransportFeedback::StatusSymbol> * vec) const258   void AppendSymbolsTo(
259       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
260     vec->insert(vec->end(), size_, symbol_);
261   }
262 
WriteTo(uint8_t * buffer) const263   void WriteTo(uint8_t* buffer) const override {
264     buffer[0] = EncodeSymbol(symbol_) << 5;  // Write S (T = 0 implicitly)
265     buffer[0] |= (size_ >> 8) & 0x1F;  // 5 most significant bits of run length.
266     buffer[1] = size_ & 0xFF;  // 8 least significant bits of run length.
267   }
268 
ParseFrom(const uint8_t * buffer)269   static RunLengthChunk* ParseFrom(const uint8_t* buffer) {
270     RTC_DCHECK_EQ(0, buffer[0] & 0x80);
271     TransportFeedback::StatusSymbol symbol =
272         DecodeSymbol((buffer[0] >> 5) & 0x03);
273     uint16_t count = (static_cast<uint16_t>(buffer[0] & 0x1F) << 8) | buffer[1];
274 
275     return new RunLengthChunk(symbol, count);
276   }
277 
278  private:
279   const TransportFeedback::StatusSymbol symbol_;
280   const size_t size_;
281 };
282 
283 // Unwrap to a larger type, for easier handling of wraps.
Unwrap(uint16_t sequence_number)284 int64_t TransportFeedback::Unwrap(uint16_t sequence_number) {
285   if (last_seq_ == -1)
286     return sequence_number;
287 
288   int64_t delta = sequence_number - last_seq_;
289   if (IsNewerSequenceNumber(sequence_number,
290                             static_cast<uint16_t>(last_seq_))) {
291     if (delta < 0)
292       delta += (1 << 16);
293   } else if (delta > 0) {
294     delta -= (1 << 16);
295   }
296 
297   return last_seq_ + delta;
298 }
299 
WithPacketSenderSsrc(uint32_t ssrc)300 void TransportFeedback::WithPacketSenderSsrc(uint32_t ssrc) {
301   packet_sender_ssrc_ = ssrc;
302 }
303 
WithMediaSourceSsrc(uint32_t ssrc)304 void TransportFeedback::WithMediaSourceSsrc(uint32_t ssrc) {
305   media_source_ssrc_ = ssrc;
306 }
307 
GetPacketSenderSsrc() const308 uint32_t TransportFeedback::GetPacketSenderSsrc() const {
309   return packet_sender_ssrc_;
310 }
311 
GetMediaSourceSsrc() const312 uint32_t TransportFeedback::GetMediaSourceSsrc() const {
313   return media_source_ssrc_;
314 }
WithBase(uint16_t base_sequence,int64_t ref_timestamp_us)315 void TransportFeedback::WithBase(uint16_t base_sequence,
316                                  int64_t ref_timestamp_us) {
317   RTC_DCHECK_EQ(-1, base_seq_);
318   RTC_DCHECK_NE(-1, ref_timestamp_us);
319   base_seq_ = base_sequence;
320   last_seq_ = base_sequence;
321   base_time_ = ref_timestamp_us / kBaseScaleFactor;
322   last_timestamp_ = base_time_ * kBaseScaleFactor;
323 }
324 
WithFeedbackSequenceNumber(uint8_t feedback_sequence)325 void TransportFeedback::WithFeedbackSequenceNumber(uint8_t feedback_sequence) {
326   feedback_seq_ = feedback_sequence;
327 }
328 
WithReceivedPacket(uint16_t sequence_number,int64_t timestamp)329 bool TransportFeedback::WithReceivedPacket(uint16_t sequence_number,
330                                            int64_t timestamp) {
331   RTC_DCHECK_NE(-1, base_seq_);
332   int64_t seq = Unwrap(sequence_number);
333   if (seq != base_seq_ && seq <= last_seq_)
334     return false;
335 
336   // Convert to ticks and round.
337   int64_t delta_full = timestamp - last_timestamp_;
338   delta_full +=
339       delta_full < 0 ? -(kDeltaScaleFactor / 2) : kDeltaScaleFactor / 2;
340   delta_full /= kDeltaScaleFactor;
341 
342   int16_t delta = static_cast<int16_t>(delta_full);
343   // If larger than 16bit signed, we can't represent it - need new fb packet.
344   if (delta != delta_full) {
345     LOG(LS_WARNING) << "Delta value too large ( >= 2^16 ticks )";
346     return false;
347   }
348 
349   StatusSymbol symbol;
350   if (delta >= 0 && delta <= 0xFF) {
351     symbol = StatusSymbol::kReceivedSmallDelta;
352   } else {
353     symbol = StatusSymbol::kReceivedLargeDelta;
354   }
355 
356   if (!AddSymbol(symbol, seq))
357     return false;
358 
359   receive_deltas_.push_back(delta);
360   last_timestamp_ += delta * kDeltaScaleFactor;
361   return true;
362 }
363 
364 // Add a symbol for a received packet, with the given sequence number. This
365 // method will add any "packet not received" symbols needed before this one.
AddSymbol(StatusSymbol symbol,int64_t seq)366 bool TransportFeedback::AddSymbol(StatusSymbol symbol, int64_t seq) {
367   while (last_seq_ < seq - 1) {
368     if (!Encode(StatusSymbol::kNotReceived))
369       return false;
370     ++last_seq_;
371   }
372 
373   if (!Encode(symbol))
374     return false;
375 
376   last_seq_ = seq;
377   return true;
378 }
379 
380 // Append a symbol to the internal symbol vector. If the new state cannot be
381 // represented using a single status chunk, a chunk will first be emitted and
382 // the associated symbols removed from the internal symbol vector.
Encode(StatusSymbol symbol)383 bool TransportFeedback::Encode(StatusSymbol symbol) {
384   if (last_seq_ - base_seq_ + 1 > 0xFFFF) {
385     LOG(LS_WARNING) << "Packet status count too large ( >= 2^16 )";
386     return false;
387   }
388 
389   bool is_two_bit;
390   int delta_size;
391   switch (symbol) {
392     case StatusSymbol::kReceivedSmallDelta:
393       delta_size = 1;
394       is_two_bit = false;
395       break;
396     case StatusSymbol::kReceivedLargeDelta:
397       delta_size = 2;
398       is_two_bit = true;
399       break;
400     case StatusSymbol::kNotReceived:
401       is_two_bit = false;
402       delta_size = 0;
403       break;
404     default:
405       RTC_NOTREACHED();
406       return false;
407   }
408 
409   if (symbol_vec_.empty()) {
410     if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
411       return false;
412 
413     symbol_vec_.push_back(symbol);
414     vec_needs_two_bit_symbols_ = is_two_bit;
415     first_symbol_cardinality_ = 1;
416     size_bytes_ += delta_size + kChunkSizeBytes;
417     return true;
418   }
419   if (size_bytes_ + delta_size > kMaxSizeBytes)
420     return false;
421 
422   // Capacity, in number of symbols, that a vector chunk could hold.
423   size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity
424                                                : kOneBitVectorCapacity;
425 
426   // first_symbol_cardinality_ is the number of times the first symbol in
427   // symbol_vec is repeated. So if that is equal to the size of symbol_vec,
428   // there is only one kind of symbol - we can potentially RLE encode it.
429   // If we have less than (capacity) symbols in symbol_vec, we can't know
430   // for certain this will be RLE-encoded; if a different symbol is added
431   // these symbols will be needed to emit a vector chunk instead. However,
432   // if first_symbol_cardinality_ > capacity, then we cannot encode the
433   // current state as a vector chunk - we must first emit symbol_vec as an
434   // RLE-chunk and then add the new symbol.
435   bool rle_candidate = symbol_vec_.size() == first_symbol_cardinality_ ||
436                        first_symbol_cardinality_ > capacity;
437   if (rle_candidate) {
438     if (symbol_vec_.back() == symbol) {
439       ++first_symbol_cardinality_;
440       if (first_symbol_cardinality_ <= capacity) {
441         symbol_vec_.push_back(symbol);
442       } else if (first_symbol_cardinality_ == kRunLengthCapacity) {
443         // Max length for an RLE-chunk reached.
444         EmitRunLengthChunk();
445       }
446       size_bytes_ += delta_size;
447       return true;
448     } else {
449       // New symbol does not match what's already in symbol_vec.
450       if (first_symbol_cardinality_ >= capacity) {
451         // Symbols in symbol_vec can only be RLE-encoded. Emit the RLE-chunk
452         // and re-add input. symbol_vec is then guaranteed to have room for the
453         // symbol, so recursion cannot continue.
454         EmitRunLengthChunk();
455         return Encode(symbol);
456       }
457       // Fall through and treat state as non RLE-candidate.
458     }
459   }
460 
461   // If this code point is reached, symbols in symbol_vec cannot be RLE-encoded.
462 
463   if (is_two_bit && !vec_needs_two_bit_symbols_) {
464     // If the symbols in symbol_vec can be encoded using a one-bit chunk but
465     // the input symbol cannot, first check if we can simply change target type.
466     vec_needs_two_bit_symbols_ = true;
467     if (symbol_vec_.size() >= kTwoBitVectorCapacity) {
468       // symbol_vec contains more symbols than we can encode in a single
469       // two-bit chunk. Emit a new vector append to the remains, if any.
470       if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
471         return false;
472       EmitVectorChunk();
473       // If symbol_vec isn't empty after emitting a vector chunk, we need to
474       // account for chunk size (otherwise handled by Encode method).
475       if (!symbol_vec_.empty())
476         size_bytes_ += kChunkSizeBytes;
477       return Encode(symbol);
478     }
479     // symbol_vec symbols fit within a single two-bit vector chunk.
480     capacity = kTwoBitVectorCapacity;
481   }
482 
483   symbol_vec_.push_back(symbol);
484   if (symbol_vec_.size() == capacity)
485     EmitVectorChunk();
486 
487   size_bytes_ += delta_size;
488   return true;
489 }
490 
491 // Upon packet completion, emit any remaining symbols in symbol_vec that have
492 // not yet been emitted in a status chunk.
EmitRemaining()493 void TransportFeedback::EmitRemaining() {
494   if (symbol_vec_.empty())
495     return;
496 
497   size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity
498                                                : kOneBitVectorCapacity;
499   if (first_symbol_cardinality_ > capacity) {
500     EmitRunLengthChunk();
501   } else {
502     EmitVectorChunk();
503   }
504 }
505 
EmitVectorChunk()506 void TransportFeedback::EmitVectorChunk() {
507   if (vec_needs_two_bit_symbols_) {
508     status_chunks_.push_back(new TwoBitVectorChunk(&symbol_vec_));
509   } else {
510     status_chunks_.push_back(new OneBitVectorChunk(&symbol_vec_));
511   }
512   // Update first symbol cardinality to match what is potentially left in in
513   // symbol_vec.
514   first_symbol_cardinality_ = 1;
515   for (size_t i = 1; i < symbol_vec_.size(); ++i) {
516     if (symbol_vec_[i] != symbol_vec_[0])
517       break;
518     ++first_symbol_cardinality_;
519   }
520 }
521 
EmitRunLengthChunk()522 void TransportFeedback::EmitRunLengthChunk() {
523   RTC_DCHECK_GE(first_symbol_cardinality_, symbol_vec_.size());
524   status_chunks_.push_back(
525       new RunLengthChunk(symbol_vec_.front(), first_symbol_cardinality_));
526   symbol_vec_.clear();
527 }
528 
BlockLength() const529 size_t TransportFeedback::BlockLength() const {
530   return size_bytes_;
531 }
532 
GetBaseSequence() const533 uint16_t TransportFeedback::GetBaseSequence() const {
534   return base_seq_;
535 }
536 
GetBaseTimeUs() const537 int64_t TransportFeedback::GetBaseTimeUs() const {
538   return base_time_ * kBaseScaleFactor;
539 }
540 
541 std::vector<TransportFeedback::StatusSymbol>
GetStatusVector() const542 TransportFeedback::GetStatusVector() const {
543   std::vector<TransportFeedback::StatusSymbol> symbols;
544   for (PacketStatusChunk* chunk : status_chunks_)
545     chunk->AppendSymbolsTo(&symbols);
546   int64_t status_count = last_seq_ - base_seq_ + 1;
547   // If packet ends with a vector chunk, it may contain extraneous "packet not
548   // received"-symbols at the end. Crop any such symbols.
549   symbols.erase(symbols.begin() + status_count, symbols.end());
550   return symbols;
551 }
552 
GetReceiveDeltas() const553 std::vector<int16_t> TransportFeedback::GetReceiveDeltas() const {
554   return receive_deltas_;
555 }
556 
GetReceiveDeltasUs() const557 std::vector<int64_t> TransportFeedback::GetReceiveDeltasUs() const {
558   if (receive_deltas_.empty())
559     return std::vector<int64_t>();
560 
561   std::vector<int64_t> us_deltas;
562   for (int16_t delta : receive_deltas_)
563     us_deltas.push_back(static_cast<int64_t>(delta) * kDeltaScaleFactor);
564 
565   return us_deltas;
566 }
567 
568 // Serialize packet.
Create(uint8_t * packet,size_t * position,size_t max_length,PacketReadyCallback * callback) const569 bool TransportFeedback::Create(uint8_t* packet,
570                                size_t* position,
571                                size_t max_length,
572                                PacketReadyCallback* callback) const {
573   if (base_seq_ == -1)
574     return false;
575 
576   while (*position + size_bytes_ > max_length) {
577     if (!OnBufferFull(packet, position, callback))
578       return false;
579   }
580 
581   CreateHeader(kFeedbackMessageType, kPayloadType, HeaderLength(), packet,
582                position);
583   ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], packet_sender_ssrc_);
584   *position += 4;
585   ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], media_source_ssrc_);
586   *position += 4;
587 
588   RTC_DCHECK_LE(base_seq_, 0xFFFF);
589   ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_);
590   *position += 2;
591 
592   int64_t status_count = last_seq_ - base_seq_ + 1;
593   RTC_DCHECK_LE(status_count, 0xFFFF);
594   ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], status_count);
595   *position += 2;
596 
597   ByteWriter<int32_t, 3>::WriteBigEndian(&packet[*position],
598                                          static_cast<int32_t>(base_time_));
599   *position += 3;
600 
601   packet[(*position)++] = feedback_seq_;
602 
603   // TODO(sprang): Get rid of this cast.
604   const_cast<TransportFeedback*>(this)->EmitRemaining();
605   for (PacketStatusChunk* chunk : status_chunks_) {
606     chunk->WriteTo(&packet[*position]);
607     *position += 2;
608   }
609 
610   for (int16_t delta : receive_deltas_) {
611     if (delta >= 0 && delta <= 0xFF) {
612       packet[(*position)++] = delta;
613     } else {
614       ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
615       *position += 2;
616     }
617   }
618 
619   while ((*position % 4) != 0)
620     packet[(*position)++] = 0;
621 
622   return true;
623 }
624 
625 //    Message format
626 //
627 //     0                   1                   2                   3
628 //     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
629 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
630 //    |V=2|P|  FMT=15 |    PT=205     |           length              |
631 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
632 //    |                     SSRC of packet sender                     |
633 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
634 //    |                      SSRC of media source                     |
635 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
636 //    |      base sequence number     |      packet status count      |
637 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
638 //    |                 reference time                | fb pkt. count |
639 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
640 //    |          packet chunk         |         packet chunk          |
641 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
642 //    .                                                               .
643 //    .                                                               .
644 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
645 //    |         packet chunk          |  recv delta   |  recv delta   |
646 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 //    .                                                               .
648 //    .                                                               .
649 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
650 //    |           recv delta          |  recv delta   | zero padding  |
651 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
652 
653 // De-serialize packet.
ParseFrom(const uint8_t * buffer,size_t length)654 rtc::scoped_ptr<TransportFeedback> TransportFeedback::ParseFrom(
655     const uint8_t* buffer,
656     size_t length) {
657   rtc::scoped_ptr<TransportFeedback> packet(new TransportFeedback());
658 
659   if (length < kMinSizeBytes) {
660     LOG(LS_WARNING) << "Buffer too small (" << length
661                     << " bytes) to fit a "
662                        "FeedbackPacket. Minimum size = " << kMinSizeBytes;
663     return nullptr;
664   }
665 
666   RTCPUtility::RtcpCommonHeader header;
667   if (!RtcpParseCommonHeader(buffer, length, &header))
668     return nullptr;
669 
670   if (header.count_or_format != kFeedbackMessageType) {
671     LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
672                     << kFeedbackMessageType << " but was "
673                     << header.count_or_format;
674     return nullptr;
675   }
676 
677   if (header.packet_type != kPayloadType) {
678     LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType
679                     << " but was " << header.packet_type;
680     return nullptr;
681   }
682 
683   packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
684   packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
685   packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]);
686   uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]);
687   packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]);
688   packet->feedback_seq_ = buffer[19];
689   size_t index = 20;
690   const size_t end_index = kHeaderLength + header.payload_size_bytes;
691 
692   if (num_packets == 0) {
693     LOG(LS_WARNING) << "Empty feedback messages not allowed.";
694     return nullptr;
695   }
696   packet->last_seq_ = packet->base_seq_ + num_packets - 1;
697 
698   size_t packets_read = 0;
699   while (packets_read < num_packets) {
700     if (index + 2 > end_index) {
701       LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
702       return nullptr;
703     }
704 
705     PacketStatusChunk* chunk =
706         ParseChunk(&buffer[index], num_packets - packets_read);
707     if (chunk == nullptr)
708       return nullptr;
709 
710     index += 2;
711     packet->status_chunks_.push_back(chunk);
712     packets_read += chunk->NumSymbols();
713   }
714 
715   std::vector<StatusSymbol> symbols = packet->GetStatusVector();
716 
717   RTC_DCHECK_EQ(num_packets, symbols.size());
718 
719   for (StatusSymbol symbol : symbols) {
720     switch (symbol) {
721       case StatusSymbol::kReceivedSmallDelta:
722         if (index + 1 > end_index) {
723           LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
724           return nullptr;
725         }
726         packet->receive_deltas_.push_back(buffer[index]);
727         ++index;
728         break;
729       case StatusSymbol::kReceivedLargeDelta:
730         if (index + 2 > end_index) {
731           LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
732           return nullptr;
733         }
734         packet->receive_deltas_.push_back(
735             ByteReader<int16_t>::ReadBigEndian(&buffer[index]));
736         index += 2;
737         break;
738       default:
739         continue;
740     }
741   }
742 
743   RTC_DCHECK_GE(index, end_index - 3);
744   RTC_DCHECK_LE(index, end_index);
745 
746   return packet;
747 }
748 
ParseChunk(const uint8_t * buffer,size_t max_size)749 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer,
750                                                  size_t max_size) {
751   if (buffer[0] & 0x80) {
752     // First bit set => vector chunk.
753     std::deque<StatusSymbol> symbols;
754     if (buffer[0] & 0x40) {
755       // Second bit set => two bits per symbol vector.
756       return TwoBitVectorChunk::ParseFrom(buffer);
757     }
758 
759     // Second bit not set => one bit per symbol vector.
760     return OneBitVectorChunk::ParseFrom(buffer);
761   }
762 
763   // First bit not set => RLE chunk.
764   RunLengthChunk* rle_chunk = RunLengthChunk::ParseFrom(buffer);
765   if (rle_chunk->NumSymbols() > max_size) {
766     LOG(LS_WARNING) << "Header/body mismatch. "
767                        "RLE block of size " << rle_chunk->NumSymbols()
768                     << " but only " << max_size << " left to read.";
769     delete rle_chunk;
770     return nullptr;
771   }
772   return rle_chunk;
773 }
774 
775 }  // namespace rtcp
776 }  // namespace webrtc
777