xref: /aosp_15_r20/external/openscreen/cast/streaming/rtcp_common.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/rtcp_common.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <algorithm>
8*3f982cf4SFabien Sanglard #include <limits>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include "cast/streaming/packet_util.h"
11*3f982cf4SFabien Sanglard #include "util/saturate_cast.h"
12*3f982cf4SFabien Sanglard 
13*3f982cf4SFabien Sanglard namespace openscreen {
14*3f982cf4SFabien Sanglard namespace cast {
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard RtcpCommonHeader::RtcpCommonHeader() = default;
17*3f982cf4SFabien Sanglard RtcpCommonHeader::~RtcpCommonHeader() = default;
18*3f982cf4SFabien Sanglard 
AppendFields(absl::Span<uint8_t> * buffer) const19*3f982cf4SFabien Sanglard void RtcpCommonHeader::AppendFields(absl::Span<uint8_t>* buffer) const {
20*3f982cf4SFabien Sanglard   OSP_CHECK_GE(buffer->size(), kRtcpCommonHeaderSize);
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard   uint8_t byte0 = kRtcpRequiredVersionAndPaddingBits
23*3f982cf4SFabien Sanglard                   << kRtcpReportCountFieldNumBits;
24*3f982cf4SFabien Sanglard   switch (packet_type) {
25*3f982cf4SFabien Sanglard     case RtcpPacketType::kSenderReport:
26*3f982cf4SFabien Sanglard     case RtcpPacketType::kReceiverReport:
27*3f982cf4SFabien Sanglard       OSP_DCHECK_LE(with.report_count,
28*3f982cf4SFabien Sanglard                     FieldBitmask<int>(kRtcpReportCountFieldNumBits));
29*3f982cf4SFabien Sanglard       byte0 |= with.report_count;
30*3f982cf4SFabien Sanglard       break;
31*3f982cf4SFabien Sanglard     case RtcpPacketType::kSourceDescription:
32*3f982cf4SFabien Sanglard       OSP_UNIMPLEMENTED();
33*3f982cf4SFabien Sanglard       break;
34*3f982cf4SFabien Sanglard     case RtcpPacketType::kApplicationDefined:
35*3f982cf4SFabien Sanglard     case RtcpPacketType::kPayloadSpecific:
36*3f982cf4SFabien Sanglard       switch (with.subtype) {
37*3f982cf4SFabien Sanglard         case RtcpSubtype::kPictureLossIndicator:
38*3f982cf4SFabien Sanglard         case RtcpSubtype::kFeedback:
39*3f982cf4SFabien Sanglard           byte0 |= static_cast<uint8_t>(with.subtype);
40*3f982cf4SFabien Sanglard           break;
41*3f982cf4SFabien Sanglard         case RtcpSubtype::kReceiverLog:
42*3f982cf4SFabien Sanglard           OSP_UNIMPLEMENTED();
43*3f982cf4SFabien Sanglard           break;
44*3f982cf4SFabien Sanglard         default:
45*3f982cf4SFabien Sanglard           OSP_NOTREACHED();
46*3f982cf4SFabien Sanglard       }
47*3f982cf4SFabien Sanglard       break;
48*3f982cf4SFabien Sanglard     case RtcpPacketType::kExtendedReports:
49*3f982cf4SFabien Sanglard       break;
50*3f982cf4SFabien Sanglard     case RtcpPacketType::kNull:
51*3f982cf4SFabien Sanglard       OSP_NOTREACHED();
52*3f982cf4SFabien Sanglard   }
53*3f982cf4SFabien Sanglard   AppendField<uint8_t>(byte0, buffer);
54*3f982cf4SFabien Sanglard 
55*3f982cf4SFabien Sanglard   AppendField<uint8_t>(static_cast<uint8_t>(packet_type), buffer);
56*3f982cf4SFabien Sanglard 
57*3f982cf4SFabien Sanglard   // The size of the packet must be evenly divisible by the 32-bit word size.
58*3f982cf4SFabien Sanglard   OSP_DCHECK_EQ(0, payload_size % sizeof(uint32_t));
59*3f982cf4SFabien Sanglard   AppendField<uint16_t>(payload_size / sizeof(uint32_t), buffer);
60*3f982cf4SFabien Sanglard }
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard // static
Parse(absl::Span<const uint8_t> buffer)63*3f982cf4SFabien Sanglard absl::optional<RtcpCommonHeader> RtcpCommonHeader::Parse(
64*3f982cf4SFabien Sanglard     absl::Span<const uint8_t> buffer) {
65*3f982cf4SFabien Sanglard   if (buffer.size() < kRtcpCommonHeaderSize) {
66*3f982cf4SFabien Sanglard     return absl::nullopt;
67*3f982cf4SFabien Sanglard   }
68*3f982cf4SFabien Sanglard 
69*3f982cf4SFabien Sanglard   const uint8_t byte0 = ConsumeField<uint8_t>(&buffer);
70*3f982cf4SFabien Sanglard   if ((byte0 >> kRtcpReportCountFieldNumBits) !=
71*3f982cf4SFabien Sanglard       kRtcpRequiredVersionAndPaddingBits) {
72*3f982cf4SFabien Sanglard     return absl::nullopt;
73*3f982cf4SFabien Sanglard   }
74*3f982cf4SFabien Sanglard   const uint8_t report_count_or_subtype =
75*3f982cf4SFabien Sanglard       byte0 & FieldBitmask<uint8_t>(kRtcpReportCountFieldNumBits);
76*3f982cf4SFabien Sanglard 
77*3f982cf4SFabien Sanglard   const uint8_t byte1 = ConsumeField<uint8_t>(&buffer);
78*3f982cf4SFabien Sanglard   if (!IsRtcpPacketType(byte1)) {
79*3f982cf4SFabien Sanglard     return absl::nullopt;
80*3f982cf4SFabien Sanglard   }
81*3f982cf4SFabien Sanglard 
82*3f982cf4SFabien Sanglard   // Optionally set |header.with.report_count| or |header.with.subtype|,
83*3f982cf4SFabien Sanglard   // depending on the packet type.
84*3f982cf4SFabien Sanglard   RtcpCommonHeader header;
85*3f982cf4SFabien Sanglard   header.packet_type = static_cast<RtcpPacketType>(byte1);
86*3f982cf4SFabien Sanglard   switch (header.packet_type) {
87*3f982cf4SFabien Sanglard     case RtcpPacketType::kSenderReport:
88*3f982cf4SFabien Sanglard     case RtcpPacketType::kReceiverReport:
89*3f982cf4SFabien Sanglard       header.with.report_count = report_count_or_subtype;
90*3f982cf4SFabien Sanglard       break;
91*3f982cf4SFabien Sanglard     case RtcpPacketType::kApplicationDefined:
92*3f982cf4SFabien Sanglard     case RtcpPacketType::kPayloadSpecific:
93*3f982cf4SFabien Sanglard       switch (static_cast<RtcpSubtype>(report_count_or_subtype)) {
94*3f982cf4SFabien Sanglard         case RtcpSubtype::kPictureLossIndicator:
95*3f982cf4SFabien Sanglard         case RtcpSubtype::kReceiverLog:
96*3f982cf4SFabien Sanglard         case RtcpSubtype::kFeedback:
97*3f982cf4SFabien Sanglard           header.with.subtype =
98*3f982cf4SFabien Sanglard               static_cast<RtcpSubtype>(report_count_or_subtype);
99*3f982cf4SFabien Sanglard           break;
100*3f982cf4SFabien Sanglard         default:  // Unknown subtype.
101*3f982cf4SFabien Sanglard           header.with.subtype = RtcpSubtype::kNull;
102*3f982cf4SFabien Sanglard           break;
103*3f982cf4SFabien Sanglard       }
104*3f982cf4SFabien Sanglard       break;
105*3f982cf4SFabien Sanglard     default:
106*3f982cf4SFabien Sanglard       // Neither |header.with.report_count| nor |header.with.subtype| are used.
107*3f982cf4SFabien Sanglard       break;
108*3f982cf4SFabien Sanglard   }
109*3f982cf4SFabien Sanglard 
110*3f982cf4SFabien Sanglard   header.payload_size =
111*3f982cf4SFabien Sanglard       static_cast<int>(ConsumeField<uint16_t>(&buffer)) * sizeof(uint32_t);
112*3f982cf4SFabien Sanglard 
113*3f982cf4SFabien Sanglard   return header;
114*3f982cf4SFabien Sanglard }
115*3f982cf4SFabien Sanglard 
116*3f982cf4SFabien Sanglard RtcpReportBlock::RtcpReportBlock() = default;
117*3f982cf4SFabien Sanglard RtcpReportBlock::~RtcpReportBlock() = default;
118*3f982cf4SFabien Sanglard 
AppendFields(absl::Span<uint8_t> * buffer) const119*3f982cf4SFabien Sanglard void RtcpReportBlock::AppendFields(absl::Span<uint8_t>* buffer) const {
120*3f982cf4SFabien Sanglard   OSP_CHECK_GE(buffer->size(), kRtcpReportBlockSize);
121*3f982cf4SFabien Sanglard 
122*3f982cf4SFabien Sanglard   AppendField<uint32_t>(ssrc, buffer);
123*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(packet_fraction_lost_numerator,
124*3f982cf4SFabien Sanglard                 std::numeric_limits<uint8_t>::min());
125*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(packet_fraction_lost_numerator,
126*3f982cf4SFabien Sanglard                 std::numeric_limits<uint8_t>::max());
127*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(cumulative_packets_lost, 0);
128*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(cumulative_packets_lost,
129*3f982cf4SFabien Sanglard                 FieldBitmask<int>(kRtcpCumulativePacketsFieldNumBits));
130*3f982cf4SFabien Sanglard   AppendField<uint32_t>(
131*3f982cf4SFabien Sanglard       (static_cast<int>(packet_fraction_lost_numerator)
132*3f982cf4SFabien Sanglard        << kRtcpCumulativePacketsFieldNumBits) |
133*3f982cf4SFabien Sanglard           (static_cast<int>(cumulative_packets_lost) &
134*3f982cf4SFabien Sanglard            FieldBitmask<uint32_t>(kRtcpCumulativePacketsFieldNumBits)),
135*3f982cf4SFabien Sanglard       buffer);
136*3f982cf4SFabien Sanglard   AppendField<uint32_t>(extended_high_sequence_number, buffer);
137*3f982cf4SFabien Sanglard   const int64_t jitter_ticks = jitter / RtpTimeDelta::FromTicks(1);
138*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(jitter_ticks, 0);
139*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(jitter_ticks, int64_t{std::numeric_limits<uint32_t>::max()});
140*3f982cf4SFabien Sanglard   AppendField<uint32_t>(jitter_ticks, buffer);
141*3f982cf4SFabien Sanglard   AppendField<uint32_t>(last_status_report_id, buffer);
142*3f982cf4SFabien Sanglard   const int64_t delay_ticks = delay_since_last_report.count();
143*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(delay_ticks, 0);
144*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(delay_ticks, int64_t{std::numeric_limits<uint32_t>::max()});
145*3f982cf4SFabien Sanglard   AppendField<uint32_t>(delay_ticks, buffer);
146*3f982cf4SFabien Sanglard }
147*3f982cf4SFabien Sanglard 
SetPacketFractionLostNumerator(int64_t num_apparently_sent,int64_t num_received)148*3f982cf4SFabien Sanglard void RtcpReportBlock::SetPacketFractionLostNumerator(
149*3f982cf4SFabien Sanglard     int64_t num_apparently_sent,
150*3f982cf4SFabien Sanglard     int64_t num_received) {
151*3f982cf4SFabien Sanglard   if (num_apparently_sent <= 0) {
152*3f982cf4SFabien Sanglard     packet_fraction_lost_numerator = 0;
153*3f982cf4SFabien Sanglard     return;
154*3f982cf4SFabien Sanglard   }
155*3f982cf4SFabien Sanglard   // The following computes the fraction of packets lost as "one minus
156*3f982cf4SFabien Sanglard   // |num_received| divided by |num_apparently_sent|" and scales by 256 (the
157*3f982cf4SFabien Sanglard   // kPacketFractionLostDenominator). It's valid for |num_received| to be
158*3f982cf4SFabien Sanglard   // greater than |num_apparently_sent| in some cases (e.g., if duplicate
159*3f982cf4SFabien Sanglard   // packets were received from the network).
160*3f982cf4SFabien Sanglard   const int64_t numerator =
161*3f982cf4SFabien Sanglard       ((num_apparently_sent - num_received) * kPacketFractionLostDenominator) /
162*3f982cf4SFabien Sanglard       num_apparently_sent;
163*3f982cf4SFabien Sanglard   // Since the value must be in the range [0,255], just do a saturate_cast
164*3f982cf4SFabien Sanglard   // to the uint8_t type to clamp.
165*3f982cf4SFabien Sanglard   packet_fraction_lost_numerator = saturate_cast<uint8_t>(numerator);
166*3f982cf4SFabien Sanglard }
167*3f982cf4SFabien Sanglard 
SetCumulativePacketsLost(int64_t num_apparently_sent,int64_t num_received)168*3f982cf4SFabien Sanglard void RtcpReportBlock::SetCumulativePacketsLost(int64_t num_apparently_sent,
169*3f982cf4SFabien Sanglard                                                int64_t num_received) {
170*3f982cf4SFabien Sanglard   const int64_t num_lost = num_apparently_sent - num_received;
171*3f982cf4SFabien Sanglard   // Clamp to valid range supported by the wire format (and RTP spec).
172*3f982cf4SFabien Sanglard   //
173*3f982cf4SFabien Sanglard   // Note that |num_lost| can be negative if duplicate packets were received.
174*3f982cf4SFabien Sanglard   // The RFC spec (https://tools.ietf.org/html/rfc3550#section-6.4.1) states
175*3f982cf4SFabien Sanglard   // this should result in a clamped, "zero loss" value.
176*3f982cf4SFabien Sanglard   cumulative_packets_lost = static_cast<int>(
177*3f982cf4SFabien Sanglard       std::min(std::max<int64_t>(num_lost, 0),
178*3f982cf4SFabien Sanglard                FieldBitmask<int64_t>(kRtcpCumulativePacketsFieldNumBits)));
179*3f982cf4SFabien Sanglard }
180*3f982cf4SFabien Sanglard 
SetDelaySinceLastReport(Clock::duration local_clock_delay)181*3f982cf4SFabien Sanglard void RtcpReportBlock::SetDelaySinceLastReport(
182*3f982cf4SFabien Sanglard     Clock::duration local_clock_delay) {
183*3f982cf4SFabien Sanglard   // Clamp to valid range supported by the wire format (and RTP spec). The
184*3f982cf4SFabien Sanglard   // bounds checking is done in terms of Clock::duration, since doing the checks
185*3f982cf4SFabien Sanglard   // after the duration_cast may allow overflow to occur in the duration_cast
186*3f982cf4SFabien Sanglard   // math (well, only for unusually large inputs).
187*3f982cf4SFabien Sanglard   constexpr Delay kMaxValidReportedDelay{std::numeric_limits<uint32_t>::max()};
188*3f982cf4SFabien Sanglard   constexpr auto kMaxValidLocalClockDelay =
189*3f982cf4SFabien Sanglard       Clock::to_duration(kMaxValidReportedDelay);
190*3f982cf4SFabien Sanglard   if (local_clock_delay > kMaxValidLocalClockDelay) {
191*3f982cf4SFabien Sanglard     delay_since_last_report = kMaxValidReportedDelay;
192*3f982cf4SFabien Sanglard     return;
193*3f982cf4SFabien Sanglard   }
194*3f982cf4SFabien Sanglard   if (local_clock_delay <= Clock::duration::zero()) {
195*3f982cf4SFabien Sanglard     delay_since_last_report = Delay::zero();
196*3f982cf4SFabien Sanglard     return;
197*3f982cf4SFabien Sanglard   }
198*3f982cf4SFabien Sanglard 
199*3f982cf4SFabien Sanglard   // If this point is reached, then the |local_clock_delay| is representable as
200*3f982cf4SFabien Sanglard   // a Delay within the valid range.
201*3f982cf4SFabien Sanglard   delay_since_last_report =
202*3f982cf4SFabien Sanglard       std::chrono::duration_cast<Delay>(local_clock_delay);
203*3f982cf4SFabien Sanglard }
204*3f982cf4SFabien Sanglard 
205*3f982cf4SFabien Sanglard // static
ParseOne(absl::Span<const uint8_t> buffer,int report_count,Ssrc ssrc)206*3f982cf4SFabien Sanglard absl::optional<RtcpReportBlock> RtcpReportBlock::ParseOne(
207*3f982cf4SFabien Sanglard     absl::Span<const uint8_t> buffer,
208*3f982cf4SFabien Sanglard     int report_count,
209*3f982cf4SFabien Sanglard     Ssrc ssrc) {
210*3f982cf4SFabien Sanglard   if (static_cast<int>(buffer.size()) < (kRtcpReportBlockSize * report_count)) {
211*3f982cf4SFabien Sanglard     return absl::nullopt;
212*3f982cf4SFabien Sanglard   }
213*3f982cf4SFabien Sanglard 
214*3f982cf4SFabien Sanglard   absl::optional<RtcpReportBlock> result;
215*3f982cf4SFabien Sanglard   for (int block = 0; block < report_count; ++block) {
216*3f982cf4SFabien Sanglard     if (ConsumeField<uint32_t>(&buffer) != ssrc) {
217*3f982cf4SFabien Sanglard       // Skip-over report block meant for some other recipient.
218*3f982cf4SFabien Sanglard       buffer.remove_prefix(kRtcpReportBlockSize - sizeof(uint32_t));
219*3f982cf4SFabien Sanglard       continue;
220*3f982cf4SFabien Sanglard     }
221*3f982cf4SFabien Sanglard 
222*3f982cf4SFabien Sanglard     RtcpReportBlock& report_block = result.emplace();
223*3f982cf4SFabien Sanglard     report_block.ssrc = ssrc;
224*3f982cf4SFabien Sanglard     const auto second_word = ConsumeField<uint32_t>(&buffer);
225*3f982cf4SFabien Sanglard     report_block.packet_fraction_lost_numerator =
226*3f982cf4SFabien Sanglard         second_word >> kRtcpCumulativePacketsFieldNumBits;
227*3f982cf4SFabien Sanglard     report_block.cumulative_packets_lost =
228*3f982cf4SFabien Sanglard         second_word &
229*3f982cf4SFabien Sanglard         FieldBitmask<uint32_t>(kRtcpCumulativePacketsFieldNumBits);
230*3f982cf4SFabien Sanglard     report_block.extended_high_sequence_number =
231*3f982cf4SFabien Sanglard         ConsumeField<uint32_t>(&buffer);
232*3f982cf4SFabien Sanglard     report_block.jitter =
233*3f982cf4SFabien Sanglard         RtpTimeDelta::FromTicks(ConsumeField<uint32_t>(&buffer));
234*3f982cf4SFabien Sanglard     report_block.last_status_report_id = ConsumeField<uint32_t>(&buffer);
235*3f982cf4SFabien Sanglard     report_block.delay_since_last_report =
236*3f982cf4SFabien Sanglard         RtcpReportBlock::Delay(ConsumeField<uint32_t>(&buffer));
237*3f982cf4SFabien Sanglard   }
238*3f982cf4SFabien Sanglard   return result;
239*3f982cf4SFabien Sanglard }
240*3f982cf4SFabien Sanglard 
241*3f982cf4SFabien Sanglard RtcpSenderReport::RtcpSenderReport() = default;
242*3f982cf4SFabien Sanglard RtcpSenderReport::~RtcpSenderReport() = default;
243*3f982cf4SFabien Sanglard 
244*3f982cf4SFabien Sanglard }  // namespace cast
245*3f982cf4SFabien Sanglard }  // namespace openscreen
246