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