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 "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
12
13 #include "modules/rtp_rtcp/source/byte_io.h"
14 #include "rtc_base/checks.h"
15 #include "rtc_base/logging.h"
16
17 namespace webrtc {
18 namespace rtcp {
19
20 // From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
21 //
22 // RTCP report block (RFC 3550).
23 //
24 // 0 1 2 3
25 // 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
26 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
27 // 0 | SSRC_1 (SSRC of first source) |
28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 // 4 | fraction lost | cumulative number of packets lost |
30 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 // 8 | extended highest sequence number received |
32 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 // 12 | interarrival jitter |
34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 // 16 | last SR (LSR) |
36 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 // 20 | delay since last SR (DLSR) |
38 // 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
ReportBlock()39 ReportBlock::ReportBlock()
40 : source_ssrc_(0),
41 fraction_lost_(0),
42 cumulative_lost_(0),
43 extended_high_seq_num_(0),
44 jitter_(0),
45 last_sr_(0),
46 delay_since_last_sr_(0) {}
47
Parse(const uint8_t * buffer,size_t length)48 bool ReportBlock::Parse(const uint8_t* buffer, size_t length) {
49 RTC_DCHECK(buffer != nullptr);
50 if (length < ReportBlock::kLength) {
51 RTC_LOG(LS_ERROR) << "Report Block should be 24 bytes long";
52 return false;
53 }
54
55 source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]);
56 fraction_lost_ = buffer[4];
57 cumulative_lost_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[5]);
58 extended_high_seq_num_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
59 jitter_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[12]);
60 last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[16]);
61 delay_since_last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[20]);
62
63 return true;
64 }
65
Create(uint8_t * buffer) const66 void ReportBlock::Create(uint8_t* buffer) const {
67 // Runtime check should be done while setting cumulative_lost.
68 RTC_DCHECK_LT(cumulative_lost_signed(),
69 (1 << 23)); // Have only 3 bytes for it.
70
71 ByteWriter<uint32_t>::WriteBigEndian(&buffer[0], source_ssrc());
72 ByteWriter<uint8_t>::WriteBigEndian(&buffer[4], fraction_lost());
73 ByteWriter<int32_t, 3>::WriteBigEndian(&buffer[5], cumulative_lost_signed());
74 ByteWriter<uint32_t>::WriteBigEndian(&buffer[8], extended_high_seq_num());
75 ByteWriter<uint32_t>::WriteBigEndian(&buffer[12], jitter());
76 ByteWriter<uint32_t>::WriteBigEndian(&buffer[16], last_sr());
77 ByteWriter<uint32_t>::WriteBigEndian(&buffer[20], delay_since_last_sr());
78 }
79
SetCumulativeLost(int32_t cumulative_lost)80 bool ReportBlock::SetCumulativeLost(int32_t cumulative_lost) {
81 // We have only 3 bytes to store it, and it's a signed value.
82 if (cumulative_lost >= (1 << 23) || cumulative_lost < -(1 << 23)) {
83 RTC_LOG(LS_WARNING)
84 << "Cumulative lost is too big to fit into Report Block";
85 return false;
86 }
87 cumulative_lost_ = cumulative_lost;
88 return true;
89 }
90
cumulative_lost() const91 uint32_t ReportBlock::cumulative_lost() const {
92 if (cumulative_lost_ < 0) {
93 RTC_LOG(LS_VERBOSE) << "Ignoring negative value of cumulative_lost";
94 return 0;
95 }
96 return cumulative_lost_;
97 }
98
99 } // namespace rtcp
100 } // namespace webrtc
101