Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc

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

Powered by Google App Engine
This is Rietveld 408576698