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 #ifndef CAST_STREAMING_RTCP_COMMON_H_
6*3f982cf4SFabien Sanglard #define CAST_STREAMING_RTCP_COMMON_H_
7*3f982cf4SFabien Sanglard
8*3f982cf4SFabien Sanglard #include <stdint.h>
9*3f982cf4SFabien Sanglard
10*3f982cf4SFabien Sanglard #include <tuple>
11*3f982cf4SFabien Sanglard #include <vector>
12*3f982cf4SFabien Sanglard
13*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
14*3f982cf4SFabien Sanglard #include "absl/types/span.h"
15*3f982cf4SFabien Sanglard #include "cast/streaming/frame_id.h"
16*3f982cf4SFabien Sanglard #include "cast/streaming/ntp_time.h"
17*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_defines.h"
18*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_time.h"
19*3f982cf4SFabien Sanglard #include "cast/streaming/ssrc.h"
20*3f982cf4SFabien Sanglard
21*3f982cf4SFabien Sanglard namespace openscreen {
22*3f982cf4SFabien Sanglard namespace cast {
23*3f982cf4SFabien Sanglard
24*3f982cf4SFabien Sanglard struct RtcpCommonHeader {
25*3f982cf4SFabien Sanglard RtcpCommonHeader();
26*3f982cf4SFabien Sanglard ~RtcpCommonHeader();
27*3f982cf4SFabien Sanglard
28*3f982cf4SFabien Sanglard RtcpPacketType packet_type = RtcpPacketType::kNull;
29*3f982cf4SFabien Sanglard
30*3f982cf4SFabien Sanglard union {
31*3f982cf4SFabien Sanglard // The number of report blocks if |packet_type| is kSenderReport or
32*3f982cf4SFabien Sanglard // kReceiverReport.
33*3f982cf4SFabien Sanglard int report_count;
34*3f982cf4SFabien Sanglard
35*3f982cf4SFabien Sanglard // Indicates the type of an application-defined message if |packet_type| is
36*3f982cf4SFabien Sanglard // kApplicationDefined or kPayloadSpecific.
37*3f982cf4SFabien Sanglard RtcpSubtype subtype;
38*3f982cf4SFabien Sanglard
39*3f982cf4SFabien Sanglard // Otherwise, not used.
40*3f982cf4SFabien Sanglard } with{0};
41*3f982cf4SFabien Sanglard
42*3f982cf4SFabien Sanglard // The size (in bytes) of the RTCP packet, not including the header.
43*3f982cf4SFabien Sanglard int payload_size = 0;
44*3f982cf4SFabien Sanglard
45*3f982cf4SFabien Sanglard // Serializes this header into the first |kRtcpCommonHeaderSize| bytes of the
46*3f982cf4SFabien Sanglard // given |buffer| and adjusts |buffer| to point to the first byte after it.
47*3f982cf4SFabien Sanglard void AppendFields(absl::Span<uint8_t>* buffer) const;
48*3f982cf4SFabien Sanglard
49*3f982cf4SFabien Sanglard // Parse from the 4-byte wire format in |buffer|. Returns nullopt if the data
50*3f982cf4SFabien Sanglard // is corrupt.
51*3f982cf4SFabien Sanglard static absl::optional<RtcpCommonHeader> Parse(
52*3f982cf4SFabien Sanglard absl::Span<const uint8_t> buffer);
53*3f982cf4SFabien Sanglard };
54*3f982cf4SFabien Sanglard
55*3f982cf4SFabien Sanglard // The middle 32-bits of the 64-bit NtpTimestamp field from the Sender Reports.
56*3f982cf4SFabien Sanglard // This is used as an opaque identifier that the Receiver will use in its
57*3f982cf4SFabien Sanglard // reports to refer to specific previous Sender Reports.
58*3f982cf4SFabien Sanglard using StatusReportId = uint32_t;
ToStatusReportId(NtpTimestamp ntp_timestamp)59*3f982cf4SFabien Sanglard constexpr StatusReportId ToStatusReportId(NtpTimestamp ntp_timestamp) {
60*3f982cf4SFabien Sanglard return static_cast<uint32_t>(ntp_timestamp >> 16);
61*3f982cf4SFabien Sanglard }
62*3f982cf4SFabien Sanglard
63*3f982cf4SFabien Sanglard // One of these is optionally included with a Sender Report or a Receiver
64*3f982cf4SFabien Sanglard // Report. See: https://tools.ietf.org/html/rfc3550#section-6.4.1
65*3f982cf4SFabien Sanglard struct RtcpReportBlock {
66*3f982cf4SFabien Sanglard RtcpReportBlock();
67*3f982cf4SFabien Sanglard ~RtcpReportBlock();
68*3f982cf4SFabien Sanglard
69*3f982cf4SFabien Sanglard // The intended recipient of this report block.
70*3f982cf4SFabien Sanglard Ssrc ssrc = 0;
71*3f982cf4SFabien Sanglard
72*3f982cf4SFabien Sanglard // The fraction of RTP packets lost since the last report, specified as a
73*3f982cf4SFabien Sanglard // variable numerator and fixed denominator. The numerator will always be in
74*3f982cf4SFabien Sanglard // the range [0,255] since, semantically:
75*3f982cf4SFabien Sanglard //
76*3f982cf4SFabien Sanglard // a. Negative values are impossible.
77*3f982cf4SFabien Sanglard // b. Values greater than 255 would indicate 100% packet loss, and so a
78*3f982cf4SFabien Sanglard // report block would not be generated in the first place.
79*3f982cf4SFabien Sanglard int packet_fraction_lost_numerator = 0;
80*3f982cf4SFabien Sanglard static constexpr int kPacketFractionLostDenominator = 256;
81*3f982cf4SFabien Sanglard
82*3f982cf4SFabien Sanglard // The total number of RTP packets lost since the start of the session. This
83*3f982cf4SFabien Sanglard // value will always be in the range [0,2^24-1], as the wire format only
84*3f982cf4SFabien Sanglard // provides 24 bits; so, wrap-around is possible.
85*3f982cf4SFabien Sanglard int cumulative_packets_lost = 0;
86*3f982cf4SFabien Sanglard
87*3f982cf4SFabien Sanglard // The highest sequence number received in any RTP packet. Wrap-around is
88*3f982cf4SFabien Sanglard // possible.
89*3f982cf4SFabien Sanglard uint32_t extended_high_sequence_number = 0;
90*3f982cf4SFabien Sanglard
91*3f982cf4SFabien Sanglard // An estimate of the recent variance in RTP packet arrival times.
92*3f982cf4SFabien Sanglard RtpTimeDelta jitter;
93*3f982cf4SFabien Sanglard
94*3f982cf4SFabien Sanglard // The last Status Report received.
95*3f982cf4SFabien Sanglard StatusReportId last_status_report_id{};
96*3f982cf4SFabien Sanglard
97*3f982cf4SFabien Sanglard // The delay between when the peer received the most-recent Status Report and
98*3f982cf4SFabien Sanglard // when this report was sent. The timebase is 65536 ticks per second and,
99*3f982cf4SFabien Sanglard // because of the wire format, this value will always be in the range
100*3f982cf4SFabien Sanglard // [0,65536) seconds.
101*3f982cf4SFabien Sanglard using Delay = std::chrono::duration<int64_t, std::ratio<1, 65536>>;
102*3f982cf4SFabien Sanglard Delay delay_since_last_report{};
103*3f982cf4SFabien Sanglard
104*3f982cf4SFabien Sanglard // Convenience helper to compute/assign the |packet_fraction_lost_numerator|,
105*3f982cf4SFabien Sanglard // based on the |num_apparently_sent| and |num_received| packet counts since
106*3f982cf4SFabien Sanglard // the last report was sent.
107*3f982cf4SFabien Sanglard void SetPacketFractionLostNumerator(int64_t num_apparently_sent,
108*3f982cf4SFabien Sanglard int64_t num_received);
109*3f982cf4SFabien Sanglard
110*3f982cf4SFabien Sanglard // Convenience helper to compute/assign the |cumulative_packets_lost|, based
111*3f982cf4SFabien Sanglard // on the |num_apparently_sent| and |num_received| packet counts since the
112*3f982cf4SFabien Sanglard // start of the entire session.
113*3f982cf4SFabien Sanglard void SetCumulativePacketsLost(int64_t num_apparently_sent,
114*3f982cf4SFabien Sanglard int64_t num_received);
115*3f982cf4SFabien Sanglard
116*3f982cf4SFabien Sanglard // Convenience helper to convert the given |local_clock_delay| to the
117*3f982cf4SFabien Sanglard // RtcpReportBlock::Delay timebase, then clamp and assign it to
118*3f982cf4SFabien Sanglard // |delay_since_last_report|.
119*3f982cf4SFabien Sanglard void SetDelaySinceLastReport(Clock::duration local_clock_delay);
120*3f982cf4SFabien Sanglard
121*3f982cf4SFabien Sanglard // Serializes this report block in the first |kRtcpReportBlockSize| bytes of
122*3f982cf4SFabien Sanglard // the given |buffer| and adjusts |buffer| to point to the first byte after
123*3f982cf4SFabien Sanglard // it.
124*3f982cf4SFabien Sanglard void AppendFields(absl::Span<uint8_t>* buffer) const;
125*3f982cf4SFabien Sanglard
126*3f982cf4SFabien Sanglard // Scans the wire-format report blocks in |buffer|, searching for one with the
127*3f982cf4SFabien Sanglard // matching |ssrc| and, if found, returns the parse result. Returns nullopt if
128*3f982cf4SFabien Sanglard // the data is corrupt or no report block with the matching SSRC was found.
129*3f982cf4SFabien Sanglard static absl::optional<RtcpReportBlock>
130*3f982cf4SFabien Sanglard ParseOne(absl::Span<const uint8_t> buffer, int report_count, Ssrc ssrc);
131*3f982cf4SFabien Sanglard };
132*3f982cf4SFabien Sanglard
133*3f982cf4SFabien Sanglard struct RtcpSenderReport {
134*3f982cf4SFabien Sanglard RtcpSenderReport();
135*3f982cf4SFabien Sanglard ~RtcpSenderReport();
136*3f982cf4SFabien Sanglard
137*3f982cf4SFabien Sanglard // The point-in-time at which this report was sent, according to both: 1) the
138*3f982cf4SFabien Sanglard // common reference clock shared by all RTP streams; 2) the RTP timestamp on
139*3f982cf4SFabien Sanglard // the media capture/playout timeline. Together, these are used by a Receiver
140*3f982cf4SFabien Sanglard // to achieve A/V synchronization across RTP streams for playout.
141*3f982cf4SFabien Sanglard Clock::time_point reference_time{};
142*3f982cf4SFabien Sanglard RtpTimeTicks rtp_timestamp;
143*3f982cf4SFabien Sanglard
144*3f982cf4SFabien Sanglard // The total number of RTP packets transmitted since the start of the session
145*3f982cf4SFabien Sanglard // (wrap-around is possible).
146*3f982cf4SFabien Sanglard uint32_t send_packet_count = 0;
147*3f982cf4SFabien Sanglard
148*3f982cf4SFabien Sanglard // The total number of payload bytes transmitted in RTP packets since the
149*3f982cf4SFabien Sanglard // start of the session (wrap-around is possible).
150*3f982cf4SFabien Sanglard uint32_t send_octet_count = 0;
151*3f982cf4SFabien Sanglard
152*3f982cf4SFabien Sanglard // The report block, if present. While the RTCP spec allows for zero or
153*3f982cf4SFabien Sanglard // multiple reports, Cast Streaming only uses zero or one.
154*3f982cf4SFabien Sanglard absl::optional<RtcpReportBlock> report_block;
155*3f982cf4SFabien Sanglard };
156*3f982cf4SFabien Sanglard
157*3f982cf4SFabien Sanglard // A pair of IDs that refers to a specific missing packet within a frame. If
158*3f982cf4SFabien Sanglard // |packet_id| is kAllPacketsLost, then it represents all the packets of a
159*3f982cf4SFabien Sanglard // frame.
160*3f982cf4SFabien Sanglard struct PacketNack {
161*3f982cf4SFabien Sanglard FrameId frame_id;
162*3f982cf4SFabien Sanglard FramePacketId packet_id;
163*3f982cf4SFabien Sanglard
164*3f982cf4SFabien Sanglard constexpr bool operator==(const PacketNack& other) const {
165*3f982cf4SFabien Sanglard return frame_id == other.frame_id && packet_id == other.packet_id;
166*3f982cf4SFabien Sanglard }
167*3f982cf4SFabien Sanglard constexpr bool operator!=(const PacketNack& other) const {
168*3f982cf4SFabien Sanglard return frame_id != other.frame_id || packet_id != other.packet_id;
169*3f982cf4SFabien Sanglard }
170*3f982cf4SFabien Sanglard constexpr bool operator<(const PacketNack& other) const {
171*3f982cf4SFabien Sanglard return (frame_id < other.frame_id) ||
172*3f982cf4SFabien Sanglard (frame_id == other.frame_id && packet_id < other.packet_id);
173*3f982cf4SFabien Sanglard }
174*3f982cf4SFabien Sanglard };
175*3f982cf4SFabien Sanglard
176*3f982cf4SFabien Sanglard } // namespace cast
177*3f982cf4SFabien Sanglard } // namespace openscreen
178*3f982cf4SFabien Sanglard
179*3f982cf4SFabien Sanglard #endif // CAST_STREAMING_RTCP_COMMON_H_
180