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