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