xref: /aosp_15_r20/external/openscreen/cast/streaming/compound_rtcp_builder.h (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 #ifndef CAST_STREAMING_COMPOUND_RTCP_BUILDER_H_
6*3f982cf4SFabien Sanglard #define CAST_STREAMING_COMPOUND_RTCP_BUILDER_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <chrono>
9*3f982cf4SFabien Sanglard #include <utility>
10*3f982cf4SFabien Sanglard #include <vector>
11*3f982cf4SFabien Sanglard 
12*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
13*3f982cf4SFabien Sanglard #include "absl/types/span.h"
14*3f982cf4SFabien Sanglard #include "cast/streaming/constants.h"
15*3f982cf4SFabien Sanglard #include "cast/streaming/frame_id.h"
16*3f982cf4SFabien Sanglard #include "cast/streaming/rtcp_common.h"
17*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_defines.h"
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard namespace openscreen {
20*3f982cf4SFabien Sanglard namespace cast {
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard class RtcpSession;
23*3f982cf4SFabien Sanglard 
24*3f982cf4SFabien Sanglard // Collects current status and feedback messages from the Receiver in the
25*3f982cf4SFabien Sanglard // current process, and builds compound RTCP packets to be transmitted to a
26*3f982cf4SFabien Sanglard // Sender.
27*3f982cf4SFabien Sanglard //
28*3f982cf4SFabien Sanglard // Usage:
29*3f982cf4SFabien Sanglard //
30*3f982cf4SFabien Sanglard //   1. Call the various SetXYZ/IncludeXYZInNextPacket() methods as the
31*3f982cf4SFabien Sanglard //      receiver's state changes. The SetXYZ() methods provide values that will
32*3f982cf4SFabien Sanglard //      be included in every RTCP packet until they are changed, while the
33*3f982cf4SFabien Sanglard //      IncludeXYZInNextPacket() methods provide values for only the next-built
34*3f982cf4SFabien Sanglard //      RTCP packet. The latter case is part of the overall protocol design, to
35*3f982cf4SFabien Sanglard //      help prevent the Sender from acting on stale Receiver state.
36*3f982cf4SFabien Sanglard //
37*3f982cf4SFabien Sanglard //   2. At certain times, call BuildPacket() and transmit it to the sender:
38*3f982cf4SFabien Sanglard //      a. By default, every 1/2 sec, to provide the sender with a "keep alive"
39*3f982cf4SFabien Sanglard //         ping that it can also use to monitor network round-trip times.
40*3f982cf4SFabien Sanglard //      b. When there is new feedback, the collected information should be
41*3f982cf4SFabien Sanglard //         immediately conveyed to the sender.
42*3f982cf4SFabien Sanglard class CompoundRtcpBuilder {
43*3f982cf4SFabien Sanglard  public:
44*3f982cf4SFabien Sanglard   explicit CompoundRtcpBuilder(RtcpSession* session);
45*3f982cf4SFabien Sanglard   ~CompoundRtcpBuilder();
46*3f982cf4SFabien Sanglard 
47*3f982cf4SFabien Sanglard   // Gets/Sets the checkpoint |frame_id| that will be included in built RTCP
48*3f982cf4SFabien Sanglard   // packets. This value indicates to the sender that all of the packets for all
49*3f982cf4SFabien Sanglard   // frames up to and including the given frame have been successfully received.
checkpoint_frame()50*3f982cf4SFabien Sanglard   FrameId checkpoint_frame() const { return checkpoint_frame_id_; }
51*3f982cf4SFabien Sanglard   void SetCheckpointFrame(FrameId frame_id);
52*3f982cf4SFabien Sanglard 
53*3f982cf4SFabien Sanglard   // Gets/Sets the current end-to-end target playout delay setting for the Cast
54*3f982cf4SFabien Sanglard   // RTP receiver, to be included in built RTCP packets. This reflect any
55*3f982cf4SFabien Sanglard   // changes the sender has made by using the "Cast Adaptive Latency Extension"
56*3f982cf4SFabien Sanglard   // in received RTP packets.
playout_delay()57*3f982cf4SFabien Sanglard   std::chrono::milliseconds playout_delay() const { return playout_delay_; }
58*3f982cf4SFabien Sanglard   void SetPlayoutDelay(std::chrono::milliseconds delay);
59*3f982cf4SFabien Sanglard 
60*3f982cf4SFabien Sanglard   // Gets/Sets the picture loss indicator flag. While this is set, built RTCP
61*3f982cf4SFabien Sanglard   // packets will include a PLI message that indicates to the sender that there
62*3f982cf4SFabien Sanglard   // has been an unrecoverable decoding error. This asks the sender to provide a
63*3f982cf4SFabien Sanglard   // key frame as soon as possible. The client must explicitly clear this flag
64*3f982cf4SFabien Sanglard   // when decoding will recover.
is_picture_loss_indicator_set()65*3f982cf4SFabien Sanglard   bool is_picture_loss_indicator_set() const { return picture_loss_indicator_; }
66*3f982cf4SFabien Sanglard   void SetPictureLossIndicator(bool picture_is_lost);
67*3f982cf4SFabien Sanglard 
68*3f982cf4SFabien Sanglard   // Include a receiver report about recent packet receive activity in ONLY the
69*3f982cf4SFabien Sanglard   // next built RTCP packet. This replaces a prior receiver report if
70*3f982cf4SFabien Sanglard   // BuildPacket() was not called in the meantime (since only the most
71*3f982cf4SFabien Sanglard   // up-to-date version of the Receiver's state is relevant to the Sender).
72*3f982cf4SFabien Sanglard   void IncludeReceiverReportInNextPacket(
73*3f982cf4SFabien Sanglard       const RtcpReportBlock& receiver_report);
74*3f982cf4SFabien Sanglard 
75*3f982cf4SFabien Sanglard   // Include detailed feedback about wholly-received frames, whole missing
76*3f982cf4SFabien Sanglard   // frames, and partially-received frames (specific missing packets) in ONLY
77*3f982cf4SFabien Sanglard   // the next built RTCP packet. The data will be included in a best-effort
78*3f982cf4SFabien Sanglard   // fashion, depending on the size of the |buffer| passed to the next call to
79*3f982cf4SFabien Sanglard   // BuildPacket(). This replaces prior feedback data if BuildPacket() was not
80*3f982cf4SFabien Sanglard   // called in the meantime (since only the most up-to-date version of the
81*3f982cf4SFabien Sanglard   // Receiver's state is relevant to the Sender).
82*3f982cf4SFabien Sanglard   //
83*3f982cf4SFabien Sanglard   // The elements in the lists are assumed to be monotonically increasing:
84*3f982cf4SFabien Sanglard   // |packet_nacks| indicates specific packets that have not yet been received,
85*3f982cf4SFabien Sanglard   // or may use kAllPacketsLost to indicate that no packets have been received
86*3f982cf4SFabien Sanglard   // for a frame. |frame_acks| indicates which frames after the checkpoint frame
87*3f982cf4SFabien Sanglard   // have been fully received.
88*3f982cf4SFabien Sanglard   void IncludeFeedbackInNextPacket(std::vector<PacketNack> packet_nacks,
89*3f982cf4SFabien Sanglard                                    std::vector<FrameId> frame_acks);
90*3f982cf4SFabien Sanglard 
91*3f982cf4SFabien Sanglard   // Builds a compound RTCP packet and returns the portion of the |buffer| that
92*3f982cf4SFabien Sanglard   // was used. The buffer's size must be at least kRequiredBufferSize, but
93*3f982cf4SFabien Sanglard   // should generally be the maximum packet size (see discussion in
94*3f982cf4SFabien Sanglard   // rtp_defines.h), to avoid dropping any ACK/NACK feedback.
95*3f982cf4SFabien Sanglard   //
96*3f982cf4SFabien Sanglard   // |send_time| specifies the when the resulting packet will be sent. This
97*3f982cf4SFabien Sanglard   // should be monotonically increasing so the consuming side (the Sender) can
98*3f982cf4SFabien Sanglard   // determine the chronological ordering of RTCP packets. The Sender might also
99*3f982cf4SFabien Sanglard   // use this to estimate round-trip times over the network.
100*3f982cf4SFabien Sanglard   absl::Span<uint8_t> BuildPacket(Clock::time_point send_time,
101*3f982cf4SFabien Sanglard                                   absl::Span<uint8_t> buffer);
102*3f982cf4SFabien Sanglard 
103*3f982cf4SFabien Sanglard   // The required buffer size to be provided to BuildPacket(). This accounts for
104*3f982cf4SFabien Sanglard   // all the possible headers and report structures that might be included,
105*3f982cf4SFabien Sanglard   // along with a reasonable amount of space for the feedback's ACK/NACKs bit
106*3f982cf4SFabien Sanglard   // vectors.
107*3f982cf4SFabien Sanglard   static constexpr int kRequiredBufferSize = 256;
108*3f982cf4SFabien Sanglard 
109*3f982cf4SFabien Sanglard  private:
110*3f982cf4SFabien Sanglard   // Helper methods called by BuildPacket() to append one RTCP packet to the
111*3f982cf4SFabien Sanglard   // |buffer| that will ultimately contain a "compound RTCP packet."
112*3f982cf4SFabien Sanglard   void AppendReceiverReportPacket(absl::Span<uint8_t>* buffer);
113*3f982cf4SFabien Sanglard   void AppendReceiverReferenceTimeReportPacket(Clock::time_point send_time,
114*3f982cf4SFabien Sanglard                                                absl::Span<uint8_t>* buffer);
115*3f982cf4SFabien Sanglard   void AppendPictureLossIndicatorPacket(absl::Span<uint8_t>* buffer);
116*3f982cf4SFabien Sanglard   void AppendCastFeedbackPacket(absl::Span<uint8_t>* buffer);
117*3f982cf4SFabien Sanglard   int AppendCastFeedbackLossFields(absl::Span<uint8_t>* buffer);
118*3f982cf4SFabien Sanglard   void AppendCastFeedbackAckFields(absl::Span<uint8_t>* buffer);
119*3f982cf4SFabien Sanglard 
120*3f982cf4SFabien Sanglard   RtcpSession* const session_;
121*3f982cf4SFabien Sanglard 
122*3f982cf4SFabien Sanglard   // Data to include in the next built RTCP packet.
123*3f982cf4SFabien Sanglard   FrameId checkpoint_frame_id_ = FrameId::leader();
124*3f982cf4SFabien Sanglard   std::chrono::milliseconds playout_delay_ = kDefaultTargetPlayoutDelay;
125*3f982cf4SFabien Sanglard   absl::optional<RtcpReportBlock> receiver_report_for_next_packet_;
126*3f982cf4SFabien Sanglard   std::vector<PacketNack> nacks_for_next_packet_;
127*3f982cf4SFabien Sanglard   std::vector<FrameId> acks_for_next_packet_;
128*3f982cf4SFabien Sanglard   bool picture_loss_indicator_ = false;
129*3f982cf4SFabien Sanglard 
130*3f982cf4SFabien Sanglard   // An 8-bit wrap-around counter that tracks how many times Cast Feedback has
131*3f982cf4SFabien Sanglard   // been included in the built RTCP packets.
132*3f982cf4SFabien Sanglard   uint8_t feedback_count_ = 0;
133*3f982cf4SFabien Sanglard };
134*3f982cf4SFabien Sanglard 
135*3f982cf4SFabien Sanglard }  // namespace cast
136*3f982cf4SFabien Sanglard }  // namespace openscreen
137*3f982cf4SFabien Sanglard 
138*3f982cf4SFabien Sanglard #endif  // CAST_STREAMING_COMPOUND_RTCP_BUILDER_H_
139