| 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 |