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

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

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

Powered by Google App Engine
This is Rietveld 408576698