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

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

Issue 1847973003: [rtcp] TransportFeedback adjusted to match other rtcp packets (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove underused buffer check from Parse, added it to Create Created 4 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
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" 11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
12 12
13 #include "webrtc/base/checks.h" 13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h" 14 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/include/module_common_types.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 16 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 17 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
17 18
18 namespace webrtc { 19 namespace webrtc {
19 namespace rtcp { 20 namespace rtcp {
20 21 namespace {
21 // Header size: 22 // Header size:
22 // * 12 bytes Common Packet Format for RTCP Feedback Messages 23 // * 4 bytes Common RTCP Packet Header
24 // * 8 bytes Common Packet Format for RTCP Feedback Messages
23 // * 8 bytes FeedbackPacket header 25 // * 8 bytes FeedbackPacket header
24 static const uint32_t kHeaderSizeBytes = 12 + 8; 26 constexpr size_t kTransportFeedbackHeaderSizeBytes = 4 + 8 + 8;
25 static const uint32_t kChunkSizeBytes = 2; 27 constexpr size_t kChunkSizeBytes = 2;
26 static const uint32_t kOneBitVectorCapacity = 14; 28 constexpr size_t kRunLengthCapacity = 0x1FFF;
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, 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. 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 31 // Size constraint imposed by RTCP common header: 16bit size field interpreted
32 // as number of four byte words minus the first header word. 32 // as number of four byte words minus the first header word.
33 static const uint32_t kMaxSizeBytes = (1 << 16) * 4; 33 constexpr size_t kMaxSizeBytes = (1 << 16) * 4;
34 static const uint32_t kMinSizeBytes = kHeaderSizeBytes + kChunkSizeBytes; 34 // Payload size:
35 static const uint32_t kBaseScaleFactor = 35 // * 8 bytes Common Packet Format for RTCP Feedback Messages
36 // * 8 bytes FeedbackPacket header.
37 // * 2 bytes for one chunk.
38 constexpr size_t kMinPayloadSizeBytes = 8 + 8 + 2;
39 constexpr size_t kBaseScaleFactor =
36 TransportFeedback::kDeltaScaleFactor * (1 << 8); 40 TransportFeedback::kDeltaScaleFactor * (1 << 8);
37 41
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) { 42 uint8_t EncodeSymbol(TransportFeedback::StatusSymbol symbol) {
48 switch (symbol) { 43 switch (symbol) {
49 case TransportFeedback::StatusSymbol::kNotReceived: 44 case TransportFeedback::StatusSymbol::kNotReceived:
50 return 0; 45 return 0;
51 case TransportFeedback::StatusSymbol::kReceivedSmallDelta: 46 case TransportFeedback::StatusSymbol::kReceivedSmallDelta:
52 return 1; 47 return 1;
53 case TransportFeedback::StatusSymbol::kReceivedLargeDelta: 48 case TransportFeedback::StatusSymbol::kReceivedLargeDelta:
54 return 2; 49 return 2;
55 default:
56 RTC_NOTREACHED();
57 return 0;
58 } 50 }
51 RTC_NOTREACHED();
52 return 0;
59 } 53 }
60 54
61 TransportFeedback::StatusSymbol DecodeSymbol(uint8_t value) { 55 TransportFeedback::StatusSymbol DecodeSymbol(uint8_t value) {
62 switch (value) { 56 switch (value) {
63 case 0: 57 case 0:
64 return TransportFeedback::StatusSymbol::kNotReceived; 58 return TransportFeedback::StatusSymbol::kNotReceived;
65 case 1: 59 case 1:
66 return TransportFeedback::StatusSymbol::kReceivedSmallDelta; 60 return TransportFeedback::StatusSymbol::kReceivedSmallDelta;
67 case 2: 61 case 2:
68 return TransportFeedback::StatusSymbol::kReceivedLargeDelta; 62 return TransportFeedback::StatusSymbol::kReceivedLargeDelta;
69 default: 63 default:
70 RTC_NOTREACHED(); 64 RTC_NOTREACHED();
71 return TransportFeedback::StatusSymbol::kNotReceived; 65 return TransportFeedback::StatusSymbol::kNotReceived;
72 } 66 }
73 } 67 }
74 68
69 } // namespace
70 constexpr uint8_t TransportFeedback::kFeedbackMessageType;
71
72 class TransportFeedback::PacketStatusChunk {
73 public:
74 virtual ~PacketStatusChunk() {}
75 virtual uint16_t NumSymbols() const = 0;
76 virtual void AppendSymbolsTo(
77 std::vector<TransportFeedback::StatusSymbol>* vec) const = 0;
78 virtual void WriteTo(uint8_t* buffer) const = 0;
79 };
80
75 TransportFeedback::TransportFeedback() 81 TransportFeedback::TransportFeedback()
76 : packet_sender_ssrc_(0), 82 : base_seq_(-1),
77 media_source_ssrc_(0),
78 base_seq_(-1),
79 base_time_(-1), 83 base_time_(-1),
80 feedback_seq_(0), 84 feedback_seq_(0),
81 last_seq_(-1), 85 last_seq_(-1),
82 last_timestamp_(-1), 86 last_timestamp_(-1),
83 first_symbol_cardinality_(0), 87 first_symbol_cardinality_(0),
84 vec_needs_two_bit_symbols_(false), 88 vec_needs_two_bit_symbols_(false),
85 size_bytes_(kHeaderSizeBytes) { 89 size_bytes_(kTransportFeedbackHeaderSizeBytes) {}
86 }
87 90
88 TransportFeedback::~TransportFeedback() { 91 TransportFeedback::~TransportFeedback() {
89 for (PacketStatusChunk* chunk : status_chunks_) 92 for (PacketStatusChunk* chunk : status_chunks_)
90 delete chunk; 93 delete chunk;
91 } 94 }
92 95
93 // One Bit Status Vector Chunk 96 // One Bit Status Vector Chunk
94 // 97 //
95 // 0 1 98 // 0 1
96 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 99 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
97 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 100 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 // |T|S| symbol list | 101 // |T|S| symbol list |
99 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 102 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 // 103 //
101 // T = 1 104 // T = 1
102 // S = 0 105 // S = 0
103 // symbol list = 14 entries where 0 = not received, 1 = received 106 // symbol list = 14 entries where 0 = not received, 1 = received
104 107
105 class OneBitVectorChunk : public PacketStatusChunk { 108 class OneBitVectorChunk : public TransportFeedback::PacketStatusChunk {
106 public: 109 public:
107 static const int kCapacity = 14; 110 static constexpr size_t kCapacity = 14;
108 111
109 explicit OneBitVectorChunk( 112 explicit OneBitVectorChunk(
110 std::deque<TransportFeedback::StatusSymbol>* symbols) { 113 std::deque<TransportFeedback::StatusSymbol>* symbols) {
111 size_t input_size = symbols->size(); 114 size_t input_size = symbols->size();
112 for (size_t i = 0; i < kCapacity; ++i) { 115 for (size_t i = 0; i < kCapacity; ++i) {
113 if (i < input_size) { 116 if (i < input_size) {
114 symbols_[i] = symbols->front(); 117 symbols_[i] = symbols->front();
115 symbols->pop_front(); 118 symbols->pop_front();
116 } else { 119 } else {
117 symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived; 120 symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived;
118 } 121 }
119 } 122 }
120 } 123 }
121 124
122 virtual ~OneBitVectorChunk() {} 125 ~OneBitVectorChunk() override {}
123 126
124 uint16_t NumSymbols() const override { return kCapacity; } 127 uint16_t NumSymbols() const override { return kCapacity; }
125 128
126 void AppendSymbolsTo( 129 void AppendSymbolsTo(
127 std::vector<TransportFeedback::StatusSymbol>* vec) const override { 130 std::vector<TransportFeedback::StatusSymbol>* vec) const override {
128 vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]); 131 vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
129 } 132 }
130 133
131 void WriteTo(uint8_t* buffer) const override { 134 void WriteTo(uint8_t* buffer) const override {
132 const int kSymbolsInFirstByte = 6; 135 constexpr int kSymbolsInFirstByte = 6;
133 const int kSymbolsInSecondByte = 8; 136 constexpr int kSymbolsInSecondByte = 8;
134 buffer[0] = 0x80u; 137 buffer[0] = 0x80u;
135 for (int i = 0; i < kSymbolsInFirstByte; ++i) { 138 for (int i = 0; i < kSymbolsInFirstByte; ++i) {
136 uint8_t encoded_symbol = EncodeSymbol(symbols_[i]); 139 uint8_t encoded_symbol = EncodeSymbol(symbols_[i]);
137 RTC_DCHECK_LE(encoded_symbol, 1u); 140 RTC_DCHECK_LE(encoded_symbol, 1u);
138 buffer[0] |= encoded_symbol << (kSymbolsInFirstByte - (i + 1)); 141 buffer[0] |= encoded_symbol << (kSymbolsInFirstByte - (i + 1));
139 } 142 }
140 buffer[1] = 0x00u; 143 buffer[1] = 0x00u;
141 for (int i = 0; i < kSymbolsInSecondByte; ++i) { 144 for (int i = 0; i < kSymbolsInSecondByte; ++i) {
142 uint8_t encoded_symbol = EncodeSymbol(symbols_[i + kSymbolsInFirstByte]); 145 uint8_t encoded_symbol = EncodeSymbol(symbols_[i + kSymbolsInFirstByte]);
143 RTC_DCHECK_LE(encoded_symbol, 1u); 146 RTC_DCHECK_LE(encoded_symbol, 1u);
(...skipping 24 matching lines...) Expand all
168 // 0 1 171 // 0 1
169 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 172 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
170 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 // |T|S| symbol list | 174 // |T|S| symbol list |
172 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 175 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 // 176 //
174 // T = 1 177 // T = 1
175 // S = 1 178 // S = 1
176 // symbol list = 7 entries of two bits each, see (Encode|Decode)Symbol 179 // symbol list = 7 entries of two bits each, see (Encode|Decode)Symbol
177 180
178 class TwoBitVectorChunk : public PacketStatusChunk { 181 class TwoBitVectorChunk : public TransportFeedback::PacketStatusChunk {
179 public: 182 public:
180 static const int kCapacity = 7; 183 static constexpr size_t kCapacity = 7;
181 184
182 explicit TwoBitVectorChunk( 185 explicit TwoBitVectorChunk(
183 std::deque<TransportFeedback::StatusSymbol>* symbols) { 186 std::deque<TransportFeedback::StatusSymbol>* symbols) {
184 size_t input_size = symbols->size(); 187 size_t input_size = symbols->size();
185 for (size_t i = 0; i < kCapacity; ++i) { 188 for (size_t i = 0; i < kCapacity; ++i) {
186 if (i < input_size) { 189 if (i < input_size) {
187 symbols_[i] = symbols->front(); 190 symbols_[i] = symbols->front();
188 symbols->pop_front(); 191 symbols->pop_front();
189 } else { 192 } else {
190 symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived; 193 symbols_[i] = TransportFeedback::StatusSymbol::kNotReceived;
191 } 194 }
192 } 195 }
193 } 196 }
194 197
195 virtual ~TwoBitVectorChunk() {} 198 ~TwoBitVectorChunk() override {}
196 199
197 uint16_t NumSymbols() const override { return kCapacity; } 200 uint16_t NumSymbols() const override { return kCapacity; }
198 201
199 void AppendSymbolsTo( 202 void AppendSymbolsTo(
200 std::vector<TransportFeedback::StatusSymbol>* vec) const override { 203 std::vector<TransportFeedback::StatusSymbol>* vec) const override {
201 vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]); 204 vec->insert(vec->end(), &symbols_[0], &symbols_[kCapacity]);
202 } 205 }
203 206
204 void WriteTo(uint8_t* buffer) const override { 207 void WriteTo(uint8_t* buffer) const override {
205 buffer[0] = 0xC0; 208 buffer[0] = 0xC0;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 // 0 1 240 // 0 1
238 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 241 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
239 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 242 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240 // |T| S | Run Length | 243 // |T| S | Run Length |
241 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 244 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242 // 245 //
243 // T = 0 246 // T = 0
244 // S = symbol, see (Encode|Decode)Symbol 247 // S = symbol, see (Encode|Decode)Symbol
245 // Run Length = Unsigned integer denoting the run length of the symbol 248 // Run Length = Unsigned integer denoting the run length of the symbol
246 249
247 class RunLengthChunk : public PacketStatusChunk { 250 class RunLengthChunk : public TransportFeedback::PacketStatusChunk {
248 public: 251 public:
249 RunLengthChunk(TransportFeedback::StatusSymbol symbol, size_t size) 252 RunLengthChunk(TransportFeedback::StatusSymbol symbol, size_t size)
250 : symbol_(symbol), size_(size) { 253 : symbol_(symbol), size_(size) {
251 RTC_DCHECK_LE(size, 0x1FFFu); 254 RTC_DCHECK_LE(size, 0x1FFFu);
252 } 255 }
253 256
254 virtual ~RunLengthChunk() {} 257 ~RunLengthChunk() override {}
255 258
256 uint16_t NumSymbols() const override { return size_; } 259 uint16_t NumSymbols() const override { return size_; }
257 260
258 void AppendSymbolsTo( 261 void AppendSymbolsTo(
259 std::vector<TransportFeedback::StatusSymbol>* vec) const override { 262 std::vector<TransportFeedback::StatusSymbol>* vec) const override {
260 vec->insert(vec->end(), size_, symbol_); 263 vec->insert(vec->end(), size_, symbol_);
261 } 264 }
262 265
263 void WriteTo(uint8_t* buffer) const override { 266 void WriteTo(uint8_t* buffer) const override {
264 buffer[0] = EncodeSymbol(symbol_) << 5; // Write S (T = 0 implicitly) 267 buffer[0] = EncodeSymbol(symbol_) << 5; // Write S (T = 0 implicitly)
(...skipping 25 matching lines...) Expand all
290 static_cast<uint16_t>(last_seq_))) { 293 static_cast<uint16_t>(last_seq_))) {
291 if (delta < 0) 294 if (delta < 0)
292 delta += (1 << 16); 295 delta += (1 << 16);
293 } else if (delta > 0) { 296 } else if (delta > 0) {
294 delta -= (1 << 16); 297 delta -= (1 << 16);
295 } 298 }
296 299
297 return last_seq_ + delta; 300 return last_seq_ + delta;
298 } 301 }
299 302
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, 303 void TransportFeedback::WithBase(uint16_t base_sequence,
316 int64_t ref_timestamp_us) { 304 int64_t ref_timestamp_us) {
317 RTC_DCHECK_EQ(-1, base_seq_); 305 RTC_DCHECK_EQ(-1, base_seq_);
318 RTC_DCHECK_NE(-1, ref_timestamp_us); 306 RTC_DCHECK_NE(-1, ref_timestamp_us);
319 base_seq_ = base_sequence; 307 base_seq_ = base_sequence;
320 // last_seq_ is the sequence number of the last packed added _before_ a call 308 // last_seq_ is the sequence number of the last packed added _before_ a call
321 // to WithReceivedPacket(). Since the first sequence to be added is 309 // to WithReceivedPacket(). Since the first sequence to be added is
322 // base_sequence, we need this to be one lower in order for potential missing 310 // base_sequence, we need this to be one lower in order for potential missing
323 // packets to be populated properly. 311 // packets to be populated properly.
324 last_seq_ = base_sequence - 1; 312 last_seq_ = base_sequence - 1;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 371
384 // Append a symbol to the internal symbol vector. If the new state cannot be 372 // Append a symbol to the internal symbol vector. If the new state cannot be
385 // represented using a single status chunk, a chunk will first be emitted and 373 // represented using a single status chunk, a chunk will first be emitted and
386 // the associated symbols removed from the internal symbol vector. 374 // the associated symbols removed from the internal symbol vector.
387 bool TransportFeedback::Encode(StatusSymbol symbol) { 375 bool TransportFeedback::Encode(StatusSymbol symbol) {
388 if (last_seq_ - base_seq_ + 1 > 0xFFFF) { 376 if (last_seq_ - base_seq_ + 1 > 0xFFFF) {
389 LOG(LS_WARNING) << "Packet status count too large ( >= 2^16 )"; 377 LOG(LS_WARNING) << "Packet status count too large ( >= 2^16 )";
390 return false; 378 return false;
391 } 379 }
392 380
393 bool is_two_bit; 381 bool is_two_bit = false;
394 int delta_size; 382 int delta_size = -1;
395 switch (symbol) { 383 switch (symbol) {
396 case StatusSymbol::kReceivedSmallDelta: 384 case StatusSymbol::kReceivedSmallDelta:
397 delta_size = 1; 385 delta_size = 1;
398 is_two_bit = false; 386 is_two_bit = false;
399 break; 387 break;
400 case StatusSymbol::kReceivedLargeDelta: 388 case StatusSymbol::kReceivedLargeDelta:
401 delta_size = 2; 389 delta_size = 2;
402 is_two_bit = true; 390 is_two_bit = true;
403 break; 391 break;
404 case StatusSymbol::kNotReceived: 392 case StatusSymbol::kNotReceived:
405 is_two_bit = false; 393 is_two_bit = false;
406 delta_size = 0; 394 delta_size = 0;
407 break; 395 break;
408 default:
409 RTC_NOTREACHED();
410 return false;
411 } 396 }
397 RTC_DCHECK_GE(delta_size, 0);
412 398
413 if (symbol_vec_.empty()) { 399 if (symbol_vec_.empty()) {
414 if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes) 400 if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
415 return false; 401 return false;
416 402
417 symbol_vec_.push_back(symbol); 403 symbol_vec_.push_back(symbol);
418 vec_needs_two_bit_symbols_ = is_two_bit; 404 vec_needs_two_bit_symbols_ = is_two_bit;
419 first_symbol_cardinality_ = 1; 405 first_symbol_cardinality_ = 1;
420 size_bytes_ += delta_size + kChunkSizeBytes; 406 size_bytes_ += delta_size + kChunkSizeBytes;
421 return true; 407 return true;
422 } 408 }
423 if (size_bytes_ + delta_size > kMaxSizeBytes) 409 if (size_bytes_ + delta_size > kMaxSizeBytes)
424 return false; 410 return false;
425 411
426 // Capacity, in number of symbols, that a vector chunk could hold. 412 // Capacity, in number of symbols, that a vector chunk could hold.
427 size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity 413 size_t capacity = vec_needs_two_bit_symbols_ ? TwoBitVectorChunk::kCapacity
428 : kOneBitVectorCapacity; 414 : OneBitVectorChunk::kCapacity;
429 415
430 // first_symbol_cardinality_ is the number of times the first symbol in 416 // first_symbol_cardinality_ is the number of times the first symbol in
431 // symbol_vec is repeated. So if that is equal to the size of symbol_vec, 417 // symbol_vec is repeated. So if that is equal to the size of symbol_vec,
432 // there is only one kind of symbol - we can potentially RLE encode it. 418 // there is only one kind of symbol - we can potentially RLE encode it.
433 // If we have less than (capacity) symbols in symbol_vec, we can't know 419 // If we have less than (capacity) symbols in symbol_vec, we can't know
434 // for certain this will be RLE-encoded; if a different symbol is added 420 // for certain this will be RLE-encoded; if a different symbol is added
435 // these symbols will be needed to emit a vector chunk instead. However, 421 // these symbols will be needed to emit a vector chunk instead. However,
436 // if first_symbol_cardinality_ > capacity, then we cannot encode the 422 // if first_symbol_cardinality_ > capacity, then we cannot encode the
437 // current state as a vector chunk - we must first emit symbol_vec as an 423 // current state as a vector chunk - we must first emit symbol_vec as an
438 // RLE-chunk and then add the new symbol. 424 // RLE-chunk and then add the new symbol.
(...skipping 22 matching lines...) Expand all
461 // Fall through and treat state as non RLE-candidate. 447 // Fall through and treat state as non RLE-candidate.
462 } 448 }
463 } 449 }
464 450
465 // If this code point is reached, symbols in symbol_vec cannot be RLE-encoded. 451 // If this code point is reached, symbols in symbol_vec cannot be RLE-encoded.
466 452
467 if (is_two_bit && !vec_needs_two_bit_symbols_) { 453 if (is_two_bit && !vec_needs_two_bit_symbols_) {
468 // If the symbols in symbol_vec can be encoded using a one-bit chunk but 454 // If the symbols in symbol_vec can be encoded using a one-bit chunk but
469 // the input symbol cannot, first check if we can simply change target type. 455 // the input symbol cannot, first check if we can simply change target type.
470 vec_needs_two_bit_symbols_ = true; 456 vec_needs_two_bit_symbols_ = true;
471 if (symbol_vec_.size() >= kTwoBitVectorCapacity) { 457 if (symbol_vec_.size() >= TwoBitVectorChunk::kCapacity) {
472 // symbol_vec contains more symbols than we can encode in a single 458 // symbol_vec contains more symbols than we can encode in a single
473 // two-bit chunk. Emit a new vector append to the remains, if any. 459 // two-bit chunk. Emit a new vector append to the remains, if any.
474 if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes) 460 if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
475 return false; 461 return false;
476 EmitVectorChunk(); 462 EmitVectorChunk();
477 // If symbol_vec isn't empty after emitting a vector chunk, we need to 463 // If symbol_vec isn't empty after emitting a vector chunk, we need to
478 // account for chunk size (otherwise handled by Encode method). 464 // account for chunk size (otherwise handled by Encode method).
479 if (!symbol_vec_.empty()) 465 if (!symbol_vec_.empty())
480 size_bytes_ += kChunkSizeBytes; 466 size_bytes_ += kChunkSizeBytes;
481 return Encode(symbol); 467 return Encode(symbol);
482 } 468 }
483 // symbol_vec symbols fit within a single two-bit vector chunk. 469 // symbol_vec symbols fit within a single two-bit vector chunk.
484 capacity = kTwoBitVectorCapacity; 470 capacity = TwoBitVectorChunk::kCapacity;
485 } 471 }
486 472
487 symbol_vec_.push_back(symbol); 473 symbol_vec_.push_back(symbol);
488 if (symbol_vec_.size() == capacity) 474 if (symbol_vec_.size() == capacity)
489 EmitVectorChunk(); 475 EmitVectorChunk();
490 476
491 size_bytes_ += delta_size; 477 size_bytes_ += delta_size;
492 return true; 478 return true;
493 } 479 }
494 480
495 // Upon packet completion, emit any remaining symbols in symbol_vec that have 481 // Upon packet completion, emit any remaining symbols in symbol_vec that have
496 // not yet been emitted in a status chunk. 482 // not yet been emitted in a status chunk.
497 void TransportFeedback::EmitRemaining() { 483 void TransportFeedback::EmitRemaining() {
498 if (symbol_vec_.empty()) 484 if (symbol_vec_.empty())
499 return; 485 return;
500 486
501 size_t capacity = vec_needs_two_bit_symbols_ ? kTwoBitVectorCapacity 487 size_t capacity = vec_needs_two_bit_symbols_ ? TwoBitVectorChunk::kCapacity
502 : kOneBitVectorCapacity; 488 : OneBitVectorChunk::kCapacity;
503 if (first_symbol_cardinality_ > capacity) { 489 if (first_symbol_cardinality_ > capacity) {
504 EmitRunLengthChunk(); 490 EmitRunLengthChunk();
505 } else { 491 } else {
506 EmitVectorChunk(); 492 EmitVectorChunk();
507 } 493 }
508 } 494 }
509 495
510 void TransportFeedback::EmitVectorChunk() { 496 void TransportFeedback::EmitVectorChunk() {
511 if (vec_needs_two_bit_symbols_) { 497 if (vec_needs_two_bit_symbols_) {
512 status_chunks_.push_back(new TwoBitVectorChunk(&symbol_vec_)); 498 status_chunks_.push_back(new TwoBitVectorChunk(&symbol_vec_));
(...skipping 11 matching lines...) Expand all
524 } 510 }
525 511
526 void TransportFeedback::EmitRunLengthChunk() { 512 void TransportFeedback::EmitRunLengthChunk() {
527 RTC_DCHECK_GE(first_symbol_cardinality_, symbol_vec_.size()); 513 RTC_DCHECK_GE(first_symbol_cardinality_, symbol_vec_.size());
528 status_chunks_.push_back( 514 status_chunks_.push_back(
529 new RunLengthChunk(symbol_vec_.front(), first_symbol_cardinality_)); 515 new RunLengthChunk(symbol_vec_.front(), first_symbol_cardinality_));
530 symbol_vec_.clear(); 516 symbol_vec_.clear();
531 } 517 }
532 518
533 size_t TransportFeedback::BlockLength() const { 519 size_t TransportFeedback::BlockLength() const {
534 return size_bytes_; 520 // Round size_bytes_ up to multiple of 32bits.
521 return (size_bytes_ + 3) & (~static_cast<size_t>(3));
535 } 522 }
536 523
537 uint16_t TransportFeedback::GetBaseSequence() const { 524 uint16_t TransportFeedback::GetBaseSequence() const {
538 return base_seq_; 525 return base_seq_;
539 } 526 }
540 527
541 int64_t TransportFeedback::GetBaseTimeUs() const { 528 int64_t TransportFeedback::GetBaseTimeUs() const {
542 return base_time_ * kBaseScaleFactor; 529 return base_time_ * kBaseScaleFactor;
543 } 530 }
544 531
(...skipping 25 matching lines...) Expand all
570 } 557 }
571 558
572 // Serialize packet. 559 // Serialize packet.
573 bool TransportFeedback::Create(uint8_t* packet, 560 bool TransportFeedback::Create(uint8_t* packet,
574 size_t* position, 561 size_t* position,
575 size_t max_length, 562 size_t max_length,
576 PacketReadyCallback* callback) const { 563 PacketReadyCallback* callback) const {
577 if (base_seq_ == -1) 564 if (base_seq_ == -1)
578 return false; 565 return false;
579 566
580 while (*position + size_bytes_ > max_length) { 567 while (*position + BlockLength() > max_length) {
581 if (!OnBufferFull(packet, position, callback)) 568 if (!OnBufferFull(packet, position, callback))
582 return false; 569 return false;
583 } 570 }
571 const size_t position_end = *position + BlockLength();
584 572
585 CreateHeader(kFeedbackMessageType, kPayloadType, HeaderLength(), packet, 573 CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
586 position); 574 position);
587 ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], packet_sender_ssrc_); 575 CreateCommonFeedback(packet + *position);
588 *position += 4; 576 *position += kCommonFeedbackLength;
589 ByteWriter<uint32_t>::WriteBigEndian(&packet[*position], media_source_ssrc_);
590 *position += 4;
591 577
592 RTC_DCHECK_LE(base_seq_, 0xFFFF); 578 RTC_DCHECK_LE(base_seq_, 0xFFFF);
593 ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_); 579 ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_);
594 *position += 2; 580 *position += 2;
595 581
596 int64_t status_count = last_seq_ - base_seq_ + 1; 582 int64_t status_count = last_seq_ - base_seq_ + 1;
597 RTC_DCHECK_LE(status_count, 0xFFFF); 583 RTC_DCHECK_LE(status_count, 0xFFFF);
598 ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], status_count); 584 ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], status_count);
599 *position += 2; 585 *position += 2;
600 586
(...skipping 15 matching lines...) Expand all
616 packet[(*position)++] = delta; 602 packet[(*position)++] = delta;
617 } else { 603 } else {
618 ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta); 604 ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
619 *position += 2; 605 *position += 2;
620 } 606 }
621 } 607 }
622 608
623 while ((*position % 4) != 0) 609 while ((*position % 4) != 0)
624 packet[(*position)++] = 0; 610 packet[(*position)++] = 0;
625 611
612 RTC_DCHECK_EQ(*position, position_end);
626 return true; 613 return true;
627 } 614 }
628 615
629 // Message format 616 // Message format
630 // 617 //
631 // 0 1 2 3 618 // 0 1 2 3
632 // 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 619 // 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
633 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 620 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
634 // |V=2|P| FMT=15 | PT=205 | length | 621 // |V=2|P| FMT=15 | PT=205 | length |
635 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 622 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
636 // | SSRC of packet sender | 623 // 0 | SSRC of packet sender |
637 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 624 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
638 // | SSRC of media source | 625 // 4 | SSRC of media source |
639 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 626 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
640 // | base sequence number | packet status count | 627 // 8 | base sequence number | packet status count |
641 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 628 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
642 // | reference time | fb pkt. count | 629 // 12 | reference time | fb pkt. count |
643 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 630 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
644 // | packet chunk | packet chunk | 631 // 16 | packet chunk | packet chunk |
645 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 632 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
646 // . . 633 // . .
647 // . . 634 // . .
648 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 635 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 // | packet chunk | recv delta | recv delta | 636 // | packet chunk | recv delta | recv delta |
650 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 637 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
651 // . . 638 // . .
652 // . . 639 // . .
653 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 640 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
654 // | recv delta | recv delta | zero padding | 641 // | recv delta | recv delta | zero padding |
655 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 642 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
656 643
657 // De-serialize packet. 644 // De-serialize packet.
658 std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom( 645 bool TransportFeedback::Parse(const CommonHeader& packet) {
659 const uint8_t* buffer, 646 RTC_DCHECK_EQ(packet.type(), kPacketType);
660 size_t length) { 647 RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType);
661 std::unique_ptr<TransportFeedback> packet(new TransportFeedback());
662 648
663 if (length < kMinSizeBytes) { 649 if (packet.payload_size_bytes() < kMinPayloadSizeBytes) {
664 LOG(LS_WARNING) << "Buffer too small (" << length 650 LOG(LS_WARNING) << "Buffer too small (" << packet.payload_size_bytes()
665 << " bytes) to fit a " 651 << " bytes) to fit a "
666 "FeedbackPacket. Minimum size = " << kMinSizeBytes; 652 "FeedbackPacket. Minimum size = "
667 return nullptr; 653 << kMinPayloadSizeBytes;
654 return false;
668 } 655 }
656 // TODO(danilchap): Make parse work correctly with not new objects.
657 RTC_DCHECK(status_chunks_.empty()) << "Parse expects object to be new.";
669 658
670 RTCPUtility::RtcpCommonHeader header; 659 const uint8_t* const payload = packet.payload();
671 if (!RtcpParseCommonHeader(buffer, length, &header))
672 return nullptr;
673 660
674 if (header.count_or_format != kFeedbackMessageType) { 661 ParseCommonFeedback(payload);
675 LOG(LS_WARNING) << "Invalid RTCP header: FMT must be "
676 << kFeedbackMessageType << " but was "
677 << header.count_or_format;
678 return nullptr;
679 }
680 662
681 if (header.packet_type != kPayloadType) { 663 base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&payload[8]);
682 LOG(LS_WARNING) << "Invalid RTCP header: PT must be " << kPayloadType 664 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&payload[10]);
683 << " but was " << header.packet_type; 665 base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&payload[12]);
684 return nullptr; 666 feedback_seq_ = payload[15];
685 } 667 size_t index = 16;
686 668 const size_t end_index = packet.payload_size_bytes();
687 packet->packet_sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
688 packet->media_source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
689 packet->base_seq_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]);
690 uint16_t num_packets = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]);
691 packet->base_time_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[16]);
692 packet->feedback_seq_ = buffer[19];
693 size_t index = 20;
694 const size_t end_index = kHeaderLength + header.payload_size_bytes;
695 669
696 if (num_packets == 0) { 670 if (num_packets == 0) {
697 LOG(LS_WARNING) << "Empty feedback messages not allowed."; 671 LOG(LS_WARNING) << "Empty feedback messages not allowed.";
698 return nullptr; 672 return false;
699 } 673 }
700 packet->last_seq_ = packet->base_seq_ + num_packets - 1; 674 last_seq_ = base_seq_ + num_packets - 1;
701 675
702 size_t packets_read = 0; 676 size_t packets_read = 0;
703 while (packets_read < num_packets) { 677 while (packets_read < num_packets) {
704 if (index + 2 > end_index) { 678 if (index + 2 > end_index) {
705 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 679 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
706 return nullptr; 680 return false;
707 } 681 }
708 682
709 PacketStatusChunk* chunk = 683 PacketStatusChunk* chunk =
710 ParseChunk(&buffer[index], num_packets - packets_read); 684 ParseChunk(&payload[index], num_packets - packets_read);
711 if (chunk == nullptr) 685 if (chunk == nullptr)
712 return nullptr; 686 return false;
713 687
714 index += 2; 688 index += 2;
715 packet->status_chunks_.push_back(chunk); 689 status_chunks_.push_back(chunk);
716 packets_read += chunk->NumSymbols(); 690 packets_read += chunk->NumSymbols();
717 } 691 }
718 692
719 std::vector<StatusSymbol> symbols = packet->GetStatusVector(); 693 std::vector<StatusSymbol> symbols = GetStatusVector();
720 694
721 RTC_DCHECK_EQ(num_packets, symbols.size()); 695 RTC_DCHECK_EQ(num_packets, symbols.size());
722 696
723 for (StatusSymbol symbol : symbols) { 697 for (StatusSymbol symbol : symbols) {
724 switch (symbol) { 698 switch (symbol) {
725 case StatusSymbol::kReceivedSmallDelta: 699 case StatusSymbol::kReceivedSmallDelta:
726 if (index + 1 > end_index) { 700 if (index + 1 > end_index) {
727 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 701 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
728 return nullptr; 702 return false;
729 } 703 }
730 packet->receive_deltas_.push_back(buffer[index]); 704 receive_deltas_.push_back(payload[index]);
731 ++index; 705 ++index;
732 break; 706 break;
733 case StatusSymbol::kReceivedLargeDelta: 707 case StatusSymbol::kReceivedLargeDelta:
734 if (index + 2 > end_index) { 708 if (index + 2 > end_index) {
735 LOG(LS_WARNING) << "Buffer overflow while parsing packet."; 709 LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
736 return nullptr; 710 return false;
737 } 711 }
738 packet->receive_deltas_.push_back( 712 receive_deltas_.push_back(
739 ByteReader<int16_t>::ReadBigEndian(&buffer[index])); 713 ByteReader<int16_t>::ReadBigEndian(&payload[index]));
740 index += 2; 714 index += 2;
741 break; 715 break;
742 default: 716 case StatusSymbol::kNotReceived:
743 continue; 717 continue;
744 } 718 }
745 } 719 }
746 720
747 RTC_DCHECK_GE(index, end_index - 3);
748 RTC_DCHECK_LE(index, end_index); 721 RTC_DCHECK_LE(index, end_index);
749 722
750 return packet; 723 return true;
751 } 724 }
752 725
753 PacketStatusChunk* TransportFeedback::ParseChunk(const uint8_t* buffer, 726 std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
754 size_t max_size) { 727 const uint8_t* buffer,
728 size_t length) {
729 CommonHeader header;
730 if (!header.Parse(buffer, length))
731 return nullptr;
732 if (header.type() != kPacketType || header.fmt() != kFeedbackMessageType)
733 return nullptr;
734 std::unique_ptr<TransportFeedback> parsed(new TransportFeedback);
735 if (!parsed->Parse(header))
736 return nullptr;
737 return parsed;
738 }
739
740 TransportFeedback::PacketStatusChunk* TransportFeedback::ParseChunk(
741 const uint8_t* buffer,
742 size_t max_size) {
755 if (buffer[0] & 0x80) { 743 if (buffer[0] & 0x80) {
756 // First bit set => vector chunk. 744 // First bit set => vector chunk.
757 std::deque<StatusSymbol> symbols;
758 if (buffer[0] & 0x40) { 745 if (buffer[0] & 0x40) {
759 // Second bit set => two bits per symbol vector. 746 // Second bit set => two bits per symbol vector.
760 return TwoBitVectorChunk::ParseFrom(buffer); 747 return TwoBitVectorChunk::ParseFrom(buffer);
761 } 748 }
762 749
763 // Second bit not set => one bit per symbol vector. 750 // Second bit not set => one bit per symbol vector.
764 return OneBitVectorChunk::ParseFrom(buffer); 751 return OneBitVectorChunk::ParseFrom(buffer);
765 } 752 }
766 753
767 // First bit not set => RLE chunk. 754 // First bit not set => RLE chunk.
768 RunLengthChunk* rle_chunk = RunLengthChunk::ParseFrom(buffer); 755 RunLengthChunk* rle_chunk = RunLengthChunk::ParseFrom(buffer);
769 if (rle_chunk->NumSymbols() > max_size) { 756 if (rle_chunk->NumSymbols() > max_size) {
770 LOG(LS_WARNING) << "Header/body mismatch. " 757 LOG(LS_WARNING) << "Header/body mismatch. "
771 "RLE block of size " << rle_chunk->NumSymbols() 758 "RLE block of size " << rle_chunk->NumSymbols()
772 << " but only " << max_size << " left to read."; 759 << " but only " << max_size << " left to read.";
773 delete rle_chunk; 760 delete rle_chunk;
774 return nullptr; 761 return nullptr;
775 } 762 }
776 return rle_chunk; 763 return rle_chunk;
777 } 764 }
778 765
779 } // namespace rtcp 766 } // namespace rtcp
780 } // namespace webrtc 767 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698