Line data Source code
1 : /*
2 : * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 : *
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
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
12 :
13 : #include <algorithm>
14 :
15 : #include "webrtc/base/checks.h"
16 : #include "webrtc/base/logging.h"
17 : #include "webrtc/modules/include/module_common_types.h"
18 : #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
19 : #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
20 :
21 : namespace webrtc {
22 : namespace rtcp {
23 : namespace {
24 : // Header size:
25 : // * 4 bytes Common RTCP Packet Header
26 : // * 8 bytes Common Packet Format for RTCP Feedback Messages
27 : // * 8 bytes FeedbackPacket header
28 : constexpr size_t kTransportFeedbackHeaderSizeBytes = 4 + 8 + 8;
29 : constexpr size_t kChunkSizeBytes = 2;
30 : // TODO(sprang): Add support for dynamic max size for easier fragmentation,
31 : // eg. set it to what's left in the buffer or IP_PACKET_SIZE.
32 : // Size constraint imposed by RTCP common header: 16bit size field interpreted
33 : // as number of four byte words minus the first header word.
34 : constexpr size_t kMaxSizeBytes = (1 << 16) * 4;
35 : // Payload size:
36 : // * 8 bytes Common Packet Format for RTCP Feedback Messages
37 : // * 8 bytes FeedbackPacket header.
38 : // * 2 bytes for one chunk.
39 : constexpr size_t kMinPayloadSizeBytes = 8 + 8 + 2;
40 : constexpr size_t kBaseScaleFactor =
41 : TransportFeedback::kDeltaScaleFactor * (1 << 8);
42 : constexpr int64_t kTimeWrapPeriodUs = (1ll << 24) * kBaseScaleFactor;
43 :
44 : // Message format
45 : //
46 : // 0 1 2 3
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
48 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 : // |V=2|P| FMT=15 | PT=205 | length |
50 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 : // 0 | SSRC of packet sender |
52 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 : // 4 | SSRC of media source |
54 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 : // 8 | base sequence number | packet status count |
56 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 : // 12 | reference time | fb pkt. count |
58 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 : // 16 | packet chunk | packet chunk |
60 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 : // . .
62 : // . .
63 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 : // | packet chunk | recv delta | recv delta |
65 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 : // . .
67 : // . .
68 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 : // | recv delta | recv delta | zero padding |
70 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 : } // namespace
72 : constexpr uint8_t TransportFeedback::kFeedbackMessageType;
73 : constexpr size_t TransportFeedback::kMaxReportedPackets;
74 :
75 : // Keep delta_sizes that can be encoded into single chunk if it is last chunk.
76 : class TransportFeedback::LastChunk {
77 : public:
78 : using DeltaSize = TransportFeedback::DeltaSize;
79 :
80 : LastChunk();
81 :
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_;
121 : };
122 : constexpr size_t TransportFeedback::LastChunk::kMaxRunLengthCapacity;
123 : constexpr size_t TransportFeedback::LastChunk::kMaxOneBitCapacity;
124 : constexpr size_t TransportFeedback::LastChunk::kMaxTwoBitCapacity;
125 : constexpr size_t TransportFeedback::LastChunk::kMaxVectorCapacity;
126 :
127 0 : TransportFeedback::LastChunk::LastChunk() {
128 0 : Clear();
129 0 : }
130 :
131 0 : bool TransportFeedback::LastChunk::Empty() const {
132 0 : return size_ == 0;
133 : }
134 :
135 0 : void TransportFeedback::LastChunk::Clear() {
136 0 : size_ = 0;
137 0 : all_same_ = true;
138 0 : has_large_delta_ = false;
139 0 : }
140 :
141 0 : bool TransportFeedback::LastChunk::CanAdd(DeltaSize delta_size) const {
142 0 : RTC_DCHECK_LE(delta_size, 2);
143 0 : if (size_ < kMaxTwoBitCapacity)
144 0 : return true;
145 0 : if (size_ < kMaxOneBitCapacity && !has_large_delta_ && delta_size != kLarge)
146 0 : return true;
147 0 : if (size_ < kMaxRunLengthCapacity && all_same_ &&
148 0 : delta_sizes_[0] == delta_size)
149 0 : return true;
150 0 : return false;
151 : }
152 :
153 0 : void TransportFeedback::LastChunk::Add(DeltaSize delta_size) {
154 0 : RTC_DCHECK(CanAdd(delta_size));
155 0 : if (size_ < kMaxVectorCapacity)
156 0 : delta_sizes_[size_] = delta_size;
157 0 : size_++;
158 0 : all_same_ = all_same_ && delta_size == delta_sizes_[0];
159 0 : has_large_delta_ = has_large_delta_ || delta_size == kLarge;
160 0 : }
161 :
162 0 : uint16_t TransportFeedback::LastChunk::Emit() {
163 0 : RTC_DCHECK(!CanAdd(0) || !CanAdd(1) || !CanAdd(2));
164 0 : if (all_same_) {
165 0 : uint16_t chunk = EncodeRunLength();
166 0 : Clear();
167 0 : return chunk;
168 : }
169 0 : if (size_ == kMaxOneBitCapacity) {
170 0 : uint16_t chunk = EncodeOneBit();
171 0 : Clear();
172 0 : return chunk;
173 : }
174 0 : RTC_DCHECK_GE(size_, kMaxTwoBitCapacity);
175 0 : uint16_t chunk = EncodeTwoBit(kMaxTwoBitCapacity);
176 : // Remove |kMaxTwoBitCapacity| encoded delta sizes:
177 : // Shift remaining delta sizes and recalculate all_same_ && has_large_delta_.
178 0 : size_ -= kMaxTwoBitCapacity;
179 0 : all_same_ = true;
180 0 : has_large_delta_ = false;
181 0 : for (size_t i = 0; i < size_; ++i) {
182 0 : DeltaSize delta_size = delta_sizes_[kMaxTwoBitCapacity + i];
183 0 : delta_sizes_[i] = delta_size;
184 0 : all_same_ = all_same_ && delta_size == delta_sizes_[0];
185 0 : has_large_delta_ = has_large_delta_ || delta_size == kLarge;
186 : }
187 :
188 0 : return chunk;
189 : }
190 :
191 0 : uint16_t TransportFeedback::LastChunk::EncodeLast() const {
192 0 : RTC_DCHECK_GT(size_, 0);
193 0 : if (all_same_)
194 0 : return EncodeRunLength();
195 0 : if (size_ <= kMaxTwoBitCapacity)
196 0 : return EncodeTwoBit(size_);
197 0 : return EncodeOneBit();
198 : }
199 :
200 : // Appends content of the Lastchunk to |deltas|.
201 0 : void TransportFeedback::LastChunk::AppendTo(
202 : std::vector<DeltaSize>* deltas) const {
203 0 : if (all_same_) {
204 0 : deltas->insert(deltas->end(), size_, delta_sizes_[0]);
205 : } else {
206 0 : deltas->insert(deltas->end(), delta_sizes_, delta_sizes_ + size_);
207 : }
208 0 : }
209 :
210 0 : void TransportFeedback::LastChunk::Decode(uint16_t chunk, size_t max_size) {
211 0 : if ((chunk & 0x8000) == 0) {
212 0 : DecodeRunLength(chunk, max_size);
213 0 : } else if ((chunk & 0x4000) == 0) {
214 0 : DecodeOneBit(chunk, max_size);
215 : } else {
216 0 : DecodeTwoBit(chunk, max_size);
217 : }
218 0 : }
219 :
220 : // One Bit Status Vector Chunk
221 : //
222 : // 0 1
223 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
224 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225 : // |T|S| symbol list |
226 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
227 : //
228 : // T = 1
229 : // S = 0
230 : // Symbol list = 14 entries where 0 = not received, 1 = received 1-byte delta.
231 0 : uint16_t TransportFeedback::LastChunk::EncodeOneBit() const {
232 0 : RTC_DCHECK(!has_large_delta_);
233 0 : RTC_DCHECK_LE(size_, kMaxOneBitCapacity);
234 0 : uint16_t chunk = 0x8000;
235 0 : for (size_t i = 0; i < size_; ++i)
236 0 : chunk |= delta_sizes_[i] << (kMaxOneBitCapacity - 1 - i);
237 0 : return chunk;
238 : }
239 :
240 0 : void TransportFeedback::LastChunk::DecodeOneBit(uint16_t chunk,
241 : size_t max_size) {
242 0 : RTC_DCHECK_EQ(chunk & 0xc000, 0x8000);
243 0 : size_ = std::min(kMaxOneBitCapacity, max_size);
244 0 : has_large_delta_ = false;
245 0 : all_same_ = false;
246 0 : for (size_t i = 0; i < size_; ++i)
247 0 : delta_sizes_[i] = (chunk >> (kMaxOneBitCapacity - 1 - i)) & 0x01;
248 0 : }
249 :
250 : // Two Bit Status Vector Chunk
251 : //
252 : // 0 1
253 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
254 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
255 : // |T|S| symbol list |
256 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
257 : //
258 : // T = 1
259 : // S = 1
260 : // symbol list = 7 entries of two bits each.
261 0 : uint16_t TransportFeedback::LastChunk::EncodeTwoBit(size_t size) const {
262 0 : RTC_DCHECK_LE(size, size_);
263 0 : uint16_t chunk = 0xc000;
264 0 : for (size_t i = 0; i < size; ++i)
265 0 : chunk |= delta_sizes_[i] << 2 * (kMaxTwoBitCapacity - 1 - i);
266 0 : return chunk;
267 : }
268 :
269 0 : void TransportFeedback::LastChunk::DecodeTwoBit(uint16_t chunk,
270 : size_t max_size) {
271 0 : RTC_DCHECK_EQ(chunk & 0xc000, 0xc000);
272 0 : size_ = std::min(kMaxTwoBitCapacity, max_size);
273 0 : has_large_delta_ = true;
274 0 : all_same_ = false;
275 0 : for (size_t i = 0; i < size_; ++i)
276 0 : delta_sizes_[i] = (chunk >> 2 * (kMaxTwoBitCapacity - 1 - i)) & 0x03;
277 0 : }
278 :
279 : // Run Length Status Vector Chunk
280 : //
281 : // 0 1
282 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
283 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
284 : // |T| S | Run Length |
285 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
286 : //
287 : // T = 0
288 : // S = symbol
289 : // Run Length = Unsigned integer denoting the run length of the symbol
290 0 : uint16_t TransportFeedback::LastChunk::EncodeRunLength() const {
291 0 : RTC_DCHECK(all_same_);
292 0 : RTC_DCHECK_LE(size_, kMaxRunLengthCapacity);
293 0 : return (delta_sizes_[0] << 13) | size_;
294 : }
295 :
296 0 : void TransportFeedback::LastChunk::DecodeRunLength(uint16_t chunk,
297 : size_t max_count) {
298 0 : RTC_DCHECK_EQ(chunk & 0x8000, 0);
299 0 : size_ = std::min<size_t>(chunk & 0x1fff, max_count);
300 0 : size_t delta_size = (chunk >> 13) & 0x03;
301 0 : has_large_delta_ = delta_size >= kLarge;
302 0 : all_same_ = true;
303 : // To make it consistent with Add function, populate delta_sizes_ beyound 1st.
304 0 : for (size_t i = 0; i < std::min<size_t>(size_, kMaxVectorCapacity); ++i)
305 0 : delta_sizes_[i] = delta_size;
306 0 : }
307 :
308 0 : 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 0 : last_chunk_(new LastChunk()),
315 0 : size_bytes_(kTransportFeedbackHeaderSizeBytes) {}
316 :
317 0 : TransportFeedback::~TransportFeedback() {}
318 :
319 0 : void TransportFeedback::SetBase(uint16_t base_sequence,
320 : int64_t ref_timestamp_us) {
321 0 : RTC_DCHECK_EQ(num_seq_no_, 0);
322 0 : RTC_DCHECK_GE(ref_timestamp_us, 0);
323 0 : base_seq_no_ = base_sequence;
324 0 : base_time_ticks_ = (ref_timestamp_us % kTimeWrapPeriodUs) / kBaseScaleFactor;
325 0 : last_timestamp_us_ = GetBaseTimeUs();
326 0 : }
327 :
328 0 : void TransportFeedback::SetFeedbackSequenceNumber(uint8_t feedback_sequence) {
329 0 : feedback_seq_ = feedback_sequence;
330 0 : }
331 :
332 0 : bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number,
333 : int64_t timestamp_us) {
334 : // Convert to ticks and round.
335 0 : int64_t delta_full = (timestamp_us - last_timestamp_us_) % kTimeWrapPeriodUs;
336 0 : if (delta_full > kTimeWrapPeriodUs / 2)
337 0 : delta_full -= kTimeWrapPeriodUs;
338 0 : delta_full +=
339 0 : delta_full < 0 ? -(kDeltaScaleFactor / 2) : kDeltaScaleFactor / 2;
340 0 : delta_full /= kDeltaScaleFactor;
341 :
342 0 : int16_t delta = static_cast<int16_t>(delta_full);
343 : // If larger than 16bit signed, we can't represent it - need new fb packet.
344 0 : if (delta != delta_full) {
345 0 : LOG(LS_WARNING) << "Delta value too large ( >= 2^16 ticks )";
346 0 : return false;
347 : }
348 :
349 0 : uint16_t next_seq_no = base_seq_no_ + num_seq_no_;
350 0 : if (sequence_number != next_seq_no) {
351 0 : uint16_t last_seq_no = next_seq_no - 1;
352 0 : if (!IsNewerSequenceNumber(sequence_number, last_seq_no))
353 0 : return false;
354 0 : for (; next_seq_no != sequence_number; ++next_seq_no)
355 0 : if (!AddDeltaSize(0))
356 0 : return false;
357 : }
358 :
359 0 : DeltaSize delta_size = (delta >= 0 && delta <= 0xff) ? 1 : 2;
360 0 : if (!AddDeltaSize(delta_size))
361 0 : return false;
362 :
363 0 : packets_.emplace_back(sequence_number, delta);
364 0 : last_timestamp_us_ += delta * kDeltaScaleFactor;
365 0 : size_bytes_ += delta_size;
366 0 : return true;
367 : }
368 :
369 0 : uint16_t TransportFeedback::GetBaseSequence() const {
370 0 : return base_seq_no_;
371 : }
372 :
373 : std::vector<TransportFeedback::StatusSymbol>
374 0 : TransportFeedback::GetStatusVector() const {
375 0 : std::vector<TransportFeedback::StatusSymbol> symbols;
376 0 : uint16_t seq_no = GetBaseSequence();
377 0 : for (const auto& packet : packets_) {
378 0 : for (; seq_no != packet.sequence_number; ++seq_no)
379 0 : symbols.push_back(StatusSymbol::kNotReceived);
380 0 : if (packet.delta_ticks >= 0x00 && packet.delta_ticks <= 0xff) {
381 0 : symbols.push_back(StatusSymbol::kReceivedSmallDelta);
382 : } else {
383 0 : symbols.push_back(StatusSymbol::kReceivedLargeDelta);
384 : }
385 0 : ++seq_no;
386 : }
387 0 : return symbols;
388 : }
389 :
390 0 : std::vector<int16_t> TransportFeedback::GetReceiveDeltas() const {
391 0 : std::vector<int16_t> deltas;
392 0 : for (const auto& packet : packets_)
393 0 : deltas.push_back(packet.delta_ticks);
394 0 : return deltas;
395 : }
396 :
397 0 : int64_t TransportFeedback::GetBaseTimeUs() const {
398 0 : return static_cast<int64_t>(base_time_ticks_) * kBaseScaleFactor;
399 : }
400 :
401 0 : std::vector<int64_t> TransportFeedback::GetReceiveDeltasUs() const {
402 0 : std::vector<int64_t> us_deltas;
403 0 : for (const auto& packet : packets_)
404 0 : us_deltas.push_back(packet.delta_ticks * kDeltaScaleFactor);
405 0 : return us_deltas;
406 : }
407 :
408 : // De-serialize packet.
409 0 : bool TransportFeedback::Parse(const CommonHeader& packet) {
410 0 : RTC_DCHECK_EQ(packet.type(), kPacketType);
411 0 : RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType);
412 :
413 0 : if (packet.payload_size_bytes() < kMinPayloadSizeBytes) {
414 0 : LOG(LS_WARNING) << "Buffer too small (" << packet.payload_size_bytes()
415 : << " bytes) to fit a "
416 0 : "FeedbackPacket. Minimum size = "
417 0 : << kMinPayloadSizeBytes;
418 0 : return false;
419 : }
420 :
421 0 : const uint8_t* const payload = packet.payload();
422 0 : ParseCommonFeedback(payload);
423 :
424 0 : base_seq_no_ = ByteReader<uint16_t>::ReadBigEndian(&payload[8]);
425 0 : size_t status_count = ByteReader<uint16_t>::ReadBigEndian(&payload[10]);
426 0 : base_time_ticks_ = ByteReader<int32_t, 3>::ReadBigEndian(&payload[12]);
427 0 : feedback_seq_ = payload[15];
428 0 : Clear();
429 0 : size_t index = 16;
430 0 : const size_t end_index = packet.payload_size_bytes();
431 :
432 0 : if (status_count == 0) {
433 0 : LOG(LS_WARNING) << "Empty feedback messages not allowed.";
434 0 : return false;
435 : }
436 :
437 0 : std::vector<uint8_t> delta_sizes;
438 0 : delta_sizes.reserve(status_count);
439 0 : while (delta_sizes.size() < status_count) {
440 0 : if (index + kChunkSizeBytes > end_index) {
441 0 : LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
442 0 : Clear();
443 0 : return false;
444 : }
445 :
446 0 : uint16_t chunk = ByteReader<uint16_t>::ReadBigEndian(&payload[index]);
447 0 : index += kChunkSizeBytes;
448 0 : encoded_chunks_.push_back(chunk);
449 0 : last_chunk_->Decode(chunk, status_count - delta_sizes.size());
450 0 : last_chunk_->AppendTo(&delta_sizes);
451 : }
452 : // Last chunk is stored in the |last_chunk_|.
453 0 : encoded_chunks_.pop_back();
454 0 : RTC_DCHECK_EQ(delta_sizes.size(), status_count);
455 0 : num_seq_no_ = status_count;
456 :
457 0 : uint16_t seq_no = base_seq_no_;
458 0 : for (size_t delta_size : delta_sizes) {
459 0 : if (index + delta_size > end_index) {
460 0 : LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
461 0 : Clear();
462 0 : return false;
463 : }
464 0 : switch (delta_size) {
465 : case 0:
466 0 : break;
467 : case 1: {
468 0 : int16_t delta = payload[index];
469 0 : packets_.emplace_back(seq_no, delta);
470 0 : last_timestamp_us_ += delta * kDeltaScaleFactor;
471 0 : index += delta_size;
472 0 : break;
473 : }
474 : case 2: {
475 0 : int16_t delta = ByteReader<int16_t>::ReadBigEndian(&payload[index]);
476 0 : packets_.emplace_back(seq_no, delta);
477 0 : last_timestamp_us_ += delta * kDeltaScaleFactor;
478 0 : index += delta_size;
479 0 : break;
480 : }
481 : case 3:
482 0 : Clear();
483 0 : LOG(LS_WARNING) << "Invalid delta_size for seq_no " << seq_no;
484 0 : return false;
485 : default:
486 0 : RTC_NOTREACHED();
487 0 : break;
488 : }
489 0 : ++seq_no;
490 : }
491 0 : size_bytes_ = RtcpPacket::kHeaderLength + index;
492 0 : RTC_DCHECK_LE(index, end_index);
493 0 : return true;
494 : }
495 :
496 0 : std::unique_ptr<TransportFeedback> TransportFeedback::ParseFrom(
497 : const uint8_t* buffer,
498 : size_t length) {
499 0 : CommonHeader header;
500 0 : if (!header.Parse(buffer, length))
501 0 : return nullptr;
502 0 : if (header.type() != kPacketType || header.fmt() != kFeedbackMessageType)
503 0 : return nullptr;
504 0 : std::unique_ptr<TransportFeedback> parsed(new TransportFeedback);
505 0 : if (!parsed->Parse(header))
506 0 : return nullptr;
507 0 : return parsed;
508 : }
509 :
510 0 : bool TransportFeedback::IsConsistent() const {
511 0 : size_t packet_size = kTransportFeedbackHeaderSizeBytes;
512 0 : std::vector<DeltaSize> delta_sizes;
513 0 : LastChunk chunk_decoder;
514 0 : for (uint16_t chunk : encoded_chunks_) {
515 0 : chunk_decoder.Decode(chunk, kMaxReportedPackets);
516 0 : chunk_decoder.AppendTo(&delta_sizes);
517 0 : packet_size += kChunkSizeBytes;
518 : }
519 0 : if (!last_chunk_->Empty()) {
520 0 : last_chunk_->AppendTo(&delta_sizes);
521 0 : packet_size += kChunkSizeBytes;
522 : }
523 0 : if (num_seq_no_ != delta_sizes.size()) {
524 0 : LOG(LS_ERROR) << delta_sizes.size() << " packets encoded. Expected "
525 0 : << num_seq_no_;
526 0 : return false;
527 : }
528 0 : int64_t timestamp_us = base_time_ticks_ * kBaseScaleFactor;
529 0 : auto packet_it = packets_.begin();
530 0 : uint16_t seq_no = base_seq_no_;
531 0 : for (DeltaSize delta_size : delta_sizes) {
532 0 : if (delta_size > 0) {
533 0 : if (packet_it == packets_.end()) {
534 0 : LOG(LS_ERROR) << "Failed to find delta for seq_no " << seq_no;
535 0 : return false;
536 : }
537 0 : if (packet_it->sequence_number != seq_no) {
538 0 : LOG(LS_ERROR) << "Expected to find delta for seq_no " << seq_no
539 0 : << ". Next delta is for " << packet_it->sequence_number;
540 0 : return false;
541 : }
542 0 : if (delta_size == 1 &&
543 0 : (packet_it->delta_ticks < 0 || packet_it->delta_ticks > 0xff)) {
544 0 : LOG(LS_ERROR) << "Delta " << packet_it->delta_ticks << " for seq_no "
545 0 : << seq_no << " doesn't fit into one byte";
546 0 : return false;
547 : }
548 0 : timestamp_us += packet_it->delta_ticks * kDeltaScaleFactor;
549 0 : ++packet_it;
550 : }
551 0 : packet_size += delta_size;
552 0 : ++seq_no;
553 : }
554 0 : if (packet_it != packets_.end()) {
555 0 : LOG(LS_ERROR) << "Unencoded delta for seq_no "
556 0 : << packet_it->sequence_number;
557 0 : return false;
558 : }
559 0 : if (timestamp_us != last_timestamp_us_) {
560 0 : LOG(LS_ERROR) << "Last timestamp mismatch. Calculated: " << timestamp_us
561 0 : << ". Saved: " << last_timestamp_us_;
562 0 : return false;
563 : }
564 0 : if (size_bytes_ != packet_size) {
565 0 : LOG(LS_ERROR) << "Rtcp packet size mismatch. Calculated: " << packet_size
566 0 : << ". Saved: " << size_bytes_;
567 0 : return false;
568 : }
569 0 : return true;
570 : }
571 :
572 : // Serialize packet.
573 0 : bool TransportFeedback::Create(uint8_t* packet,
574 : size_t* position,
575 : size_t max_length,
576 : PacketReadyCallback* callback) const {
577 0 : if (num_seq_no_ == 0)
578 0 : return false;
579 :
580 0 : while (*position + BlockLength() > max_length) {
581 0 : if (!OnBufferFull(packet, position, callback))
582 0 : return false;
583 : }
584 0 : const size_t position_end = *position + BlockLength();
585 :
586 0 : CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
587 0 : position);
588 0 : CreateCommonFeedback(packet + *position);
589 0 : *position += kCommonFeedbackLength;
590 :
591 0 : ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], base_seq_no_);
592 0 : *position += 2;
593 :
594 0 : ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], num_seq_no_);
595 0 : *position += 2;
596 :
597 0 : ByteWriter<int32_t, 3>::WriteBigEndian(&packet[*position], base_time_ticks_);
598 0 : *position += 3;
599 :
600 0 : packet[(*position)++] = feedback_seq_;
601 :
602 0 : for (uint16_t chunk : encoded_chunks_) {
603 0 : ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], chunk);
604 0 : *position += 2;
605 : }
606 0 : if (!last_chunk_->Empty()) {
607 0 : uint16_t chunk = last_chunk_->EncodeLast();
608 0 : ByteWriter<uint16_t>::WriteBigEndian(&packet[*position], chunk);
609 0 : *position += 2;
610 : }
611 :
612 0 : for (const auto& received_packet : packets_) {
613 0 : int16_t delta = received_packet.delta_ticks;
614 0 : if (delta >= 0 && delta <= 0xFF) {
615 0 : packet[(*position)++] = delta;
616 : } else {
617 0 : ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
618 0 : *position += 2;
619 : }
620 : }
621 :
622 0 : while ((*position % 4) != 0)
623 0 : packet[(*position)++] = 0;
624 :
625 0 : RTC_DCHECK_EQ(*position, position_end);
626 0 : return true;
627 : }
628 :
629 0 : size_t TransportFeedback::BlockLength() const {
630 : // Round size_bytes_ up to multiple of 32bits.
631 0 : return (size_bytes_ + 3) & (~static_cast<size_t>(3));
632 : }
633 :
634 0 : void TransportFeedback::Clear() {
635 0 : num_seq_no_ = 0;
636 0 : last_timestamp_us_ = GetBaseTimeUs();
637 0 : packets_.clear();
638 0 : encoded_chunks_.clear();
639 0 : last_chunk_->Clear();
640 0 : size_bytes_ = kTransportFeedbackHeaderSizeBytes;
641 0 : }
642 :
643 0 : bool TransportFeedback::AddDeltaSize(DeltaSize delta_size) {
644 0 : if (num_seq_no_ == kMaxReportedPackets)
645 0 : return false;
646 0 : size_t add_chunk_size = last_chunk_->Empty() ? kChunkSizeBytes : 0;
647 0 : if (size_bytes_ + delta_size + add_chunk_size > kMaxSizeBytes)
648 0 : return false;
649 :
650 0 : if (last_chunk_->CanAdd(delta_size)) {
651 0 : size_bytes_ += add_chunk_size;
652 0 : last_chunk_->Add(delta_size);
653 0 : ++num_seq_no_;
654 0 : return true;
655 : }
656 0 : if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes)
657 0 : return false;
658 :
659 0 : encoded_chunks_.push_back(last_chunk_->Emit());
660 0 : size_bytes_ += kChunkSizeBytes;
661 0 : last_chunk_->Add(delta_size);
662 0 : ++num_seq_no_;
663 0 : return true;
664 : }
665 :
666 : } // namespace rtcp
667 : } // namespace webrtc
|