Home | History | Annotate | Download | only in rtcp_packet
      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:
     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 
     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 
     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 
     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 
     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 
    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 
    122   virtual ~OneBitVectorChunk() {}
    123 
    124   uint16_t NumSymbols() const override { return kCapacity; }
    125 
    126   void AppendSymbolsTo(
    127       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
    128     vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
    129   }
    130 
    131   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 
    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:
    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 
    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 
    195   virtual ~TwoBitVectorChunk() {}
    196 
    197   uint16_t NumSymbols() const override { return kCapacity; }
    198 
    199   void AppendSymbolsTo(
    200       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
    201     vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
    202   }
    203 
    204   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 
    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:
    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:
    249   RunLengthChunk(TransportFeedback::StatusSymbol symbol, size_t size)
    250       : symbol_(symbol), size_(size) {
    251     RTC_DCHECK_LE(size, 0x1FFFu);
    252   }
    253 
    254   virtual ~RunLengthChunk() {}
    255 
    256   uint16_t NumSymbols() const override { return size_; }
    257 
    258   void AppendSymbolsTo(
    259       std::vector<TransportFeedback::StatusSymbol>* vec) const override {
    260     vec->insert(vec->end(), size_, symbol_);
    261   }
    262 
    263   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 
    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.
    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 
    300 void TransportFeedback::WithPacketSenderSsrc(uint32_t ssrc) {
    301   packet_sender_ssrc_ = ssrc;
    302 }
    303 
    304 void TransportFeedback::WithMediaSourceSsrc(uint32_t ssrc) {
    305   media_source_ssrc_ = ssrc;
    306 }
    307 
    308 uint32_t TransportFeedback::GetPacketSenderSsrc() const {
    309   return packet_sender_ssrc_;
    310 }
    311 
    312 uint32_t TransportFeedback::GetMediaSourceSsrc() const {
    313   return media_source_ssrc_;
    314 }
    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 
    325 void TransportFeedback::WithFeedbackSequenceNumber(uint8_t feedback_sequence) {
    326   feedback_seq_ = feedback_sequence;
    327 }
    328 
    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.
    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.
    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.
    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 
    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 
    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 
    529 size_t TransportFeedback::BlockLength() const {
    530   return size_bytes_;
    531 }
    532 
    533 uint16_t TransportFeedback::GetBaseSequence() const {
    534   return base_seq_;
    535 }
    536 
    537 int64_t TransportFeedback::GetBaseTimeUs() const {
    538   return base_time_ * kBaseScaleFactor;
    539 }
    540 
    541 std::vector<TransportFeedback::StatusSymbol>
    542 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 
    553 std::vector<int16_t> TransportFeedback::GetReceiveDeltas() const {
    554   return receive_deltas_;
    555 }
    556 
    557 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.
    569 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.
    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 
    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