OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |