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

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

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

Powered by Google App Engine
This is Rietveld 408576698