1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CAST_STREAMING_SENDER_H_ 6 #define CAST_STREAMING_SENDER_H_ 7 8 #include <stdint.h> 9 10 #include <array> 11 #include <chrono> 12 #include <vector> 13 14 #include "absl/types/span.h" 15 #include "cast/streaming/compound_rtcp_parser.h" 16 #include "cast/streaming/constants.h" 17 #include "cast/streaming/frame_crypto.h" 18 #include "cast/streaming/frame_id.h" 19 #include "cast/streaming/rtp_defines.h" 20 #include "cast/streaming/rtp_packetizer.h" 21 #include "cast/streaming/rtp_time.h" 22 #include "cast/streaming/sender_packet_router.h" 23 #include "cast/streaming/sender_report_builder.h" 24 #include "cast/streaming/session_config.h" 25 #include "platform/api/time.h" 26 #include "util/yet_another_bit_vector.h" 27 28 namespace openscreen { 29 namespace cast { 30 31 class Environment; 32 33 // The Cast Streaming Sender, a peer corresponding to some Cast Streaming 34 // Receiver at the other end of a network link. See class level comments for 35 // Receiver for a high-level overview. 36 // 37 // The Sender is the peer responsible for enqueuing EncodedFrames for streaming, 38 // guaranteeing their delivery to a Receiver, and handling feedback events from 39 // a Receiver. Some feedback events are used for managing the Sender's internal 40 // queue of in-flight frames, requesting network packet re-transmits, etc.; 41 // while others are exposed via the Sender's public interface. For example, 42 // sometimes the Receiver signals that it needs a a key frame to resolve a 43 // picture loss condition, and the modules upstream of the Sender (e.g., where 44 // encoding happens) should call NeedsKeyFrame() to check for, and handle that. 45 // 46 // There are usually one or two Senders in a streaming session, one for audio 47 // and one for video. Both senders work with the same SenderPacketRouter 48 // instance to schedule their transmission of packets, and provide the necessary 49 // metrics for estimating bandwidth utilization and availability. 50 // 51 // It is the responsibility of upstream code modules to handle congestion 52 // control. With respect to this Sender, that means the media encoding bit rate 53 // should be throttled based on network bandwidth availability. This Sender does 54 // not do any throttling, only flow-control. In other words, this Sender can 55 // only manage its in-flight queue of frames, and if that queue grows too large, 56 // it will eventually reject further enqueuing. 57 // 58 // General usage: A client should check the in-flight media duration frequently 59 // to decide when to pause encoding, to avoid wasting system resources on 60 // encoding frames that will likely be rejected by the Sender. The client should 61 // also frequently call NeedsKeyFrame() and, when this returns true, direct its 62 // encoder to produce a key frame soon. Finally, when using EnqueueFrame(), an 63 // EncodedFrame struct should be prepared with its frame_id field set to 64 // whatever GetNextFrameId() returns. Please see method comments for 65 // more-detailed usage info. 66 class Sender final : public SenderPacketRouter::Sender, 67 public CompoundRtcpParser::Client { 68 public: 69 // Interface for receiving notifications about events of possible interest. 70 // Handling each of these is optional, but some may be mandatory for certain 71 // applications (see method comments below). 72 class Observer { 73 public: 74 // Called when a frame was canceled. "Canceled" means that the Receiver has 75 // either acknowledged successful receipt of the frame or has decided to 76 // skip over it. Note: Frame cancellations may occur out-of-order. 77 virtual void OnFrameCanceled(FrameId frame_id); 78 79 // Called when a Receiver begins reporting picture loss, and there is no key 80 // frame currently enqueued in the Sender. The application should enqueue a 81 // key frame as soon as possible. Note: An application that pauses frame 82 // sending (e.g., screen mirroring when the screen is not changing) should 83 // use this notification to send an out-of-band "refresh frame," encoded as 84 // a key frame. 85 virtual void OnPictureLost(); 86 87 protected: 88 virtual ~Observer(); 89 }; 90 91 // Result codes for EnqueueFrame(). 92 enum EnqueueFrameResult { 93 // The frame has been queued for sending. 94 OK, 95 96 // The frame's payload was too large. This is typically triggered when 97 // submitting a payload of several dozen megabytes or more. This result code 98 // likely indicates some kind of upstream bug. 99 PAYLOAD_TOO_LARGE, 100 101 // The span of FrameIds is too large. Cast Streaming's protocol design 102 // imposes a limit in the maximum difference between the highest-valued 103 // in-flight FrameId and the least-valued one. 104 REACHED_ID_SPAN_LIMIT, 105 106 // Too-large a media duration is in-flight. Enqueuing another frame would 107 // automatically cause late play-out at the Receiver. 108 MAX_DURATION_IN_FLIGHT, 109 }; 110 111 // Constructs a Sender that attaches to the given |environment|-provided 112 // resources and |packet_router|. The |config| contains the settings that were 113 // agreed-upon by both sides from the OFFER/ANSWER exchange (i.e., the part of 114 // the overall end-to-end connection process that occurs before Cast Streaming 115 // is started). The |rtp_payload_type| does not affect the behavior of this 116 // Sender. It is simply passed along to a Receiver in the RTP packet stream. 117 Sender(Environment* environment, 118 SenderPacketRouter* packet_router, 119 SessionConfig config, 120 RtpPayloadType rtp_payload_type); 121 122 ~Sender() final; 123 config()124 const SessionConfig& config() const { return config_; } ssrc()125 Ssrc ssrc() const { return rtcp_session_.sender_ssrc(); } rtp_timebase()126 int rtp_timebase() const { return rtp_timebase_; } 127 128 // Sets an observer for receiving notifications. Call with nullptr to stop 129 // observing. 130 void SetObserver(Observer* observer); 131 132 // Returns the number of frames currently in-flight. This is only meant to be 133 // informative. Clients should use GetInFlightMediaDuration() to make 134 // throttling decisions. 135 int GetInFlightFrameCount() const; 136 137 // Returns the total media duration of the frames currently in-flight, 138 // assuming the next not-yet-enqueued frame will have the given RTP timestamp. 139 // For a better user experience, the result should be compared to 140 // GetMaxInFlightMediaDuration(), and media encoding should be throttled down 141 // before additional EnqueueFrame() calls would cause this to reach the 142 // current maximum limit. 143 Clock::duration GetInFlightMediaDuration( 144 RtpTimeTicks next_frame_rtp_timestamp) const; 145 146 // Return the maximum acceptable in-flight media duration, given the current 147 // target playout delay setting and end-to-end network/system conditions. 148 Clock::duration GetMaxInFlightMediaDuration() const; 149 150 // Returns true if the Receiver requires a key frame. Note that this will 151 // return true until a key frame is accepted by EnqueueFrame(). Thus, when 152 // encoding is pipelined, care should be taken to instruct the encoder to 153 // produce just ONE forced key frame. 154 bool NeedsKeyFrame() const; 155 156 // Returns the next FrameId, the one after the frame enqueued by the last call 157 // to EnqueueFrame(). Note that the next call to EnqueueFrame() assumes this 158 // frame ID be used. 159 FrameId GetNextFrameId() const; 160 161 // Enqueues the given |frame| for sending as soon as possible. Returns OK if 162 // the frame is accepted, and some time later Observer::OnFrameCanceled() will 163 // be called once it is no longer in-flight. 164 // 165 // All fields of the |frame| must be set to valid values: the |frame_id| must 166 // be the same as GetNextFrameId(); both the |rtp_timestamp| and 167 // |reference_time| fields must be monotonically increasing relative to the 168 // prior frame; and the frame's |data| pointer must be set. 169 [[nodiscard]] EnqueueFrameResult EnqueueFrame(const EncodedFrame& frame); 170 171 // Causes all pending operations to discard data when they are processed 172 // later. 173 void CancelInFlightData(); 174 175 private: 176 // Tracking/Storage for frames that are ready-to-send, and until they are 177 // fully received at the other end. 178 struct PendingFrameSlot { 179 // The frame to send, or nullopt if this slot is not in use. 180 absl::optional<EncryptedFrame> frame; 181 182 // Represents which packets need to be sent. Elements are indexed by 183 // FramePacketId. A set bit means a packet needs to be sent (or re-sent). 184 YetAnotherBitVector send_flags; 185 186 // The time when each of the packets was last sent, or 187 // |SenderPacketRouter::kNever| if the packet has not been sent yet. 188 // Elements are indexed by FramePacketId. This is used to avoid 189 // re-transmitting any given packet too frequently. 190 std::vector<Clock::time_point> packet_sent_times; 191 192 PendingFrameSlot(); 193 ~PendingFrameSlot(); 194 is_active_for_framePendingFrameSlot195 bool is_active_for_frame(FrameId frame_id) const { 196 return frame && frame->frame_id == frame_id; 197 } 198 }; 199 200 // Return value from the ChooseXYZ() helper methods. 201 struct ChosenPacket { 202 PendingFrameSlot* slot = nullptr; 203 FramePacketId packet_id{}; 204 205 explicit operator bool() const { return !!slot; } 206 }; 207 208 // An extension of ChosenPacket that also includes the point-in-time when the 209 // packet should be sent. 210 struct ChosenPacketAndWhen : public ChosenPacket { 211 Clock::time_point when = SenderPacketRouter::kNever; 212 }; 213 214 // SenderPacketRouter::Sender implementation. 215 void OnReceivedRtcpPacket(Clock::time_point arrival_time, 216 absl::Span<const uint8_t> packet) final; 217 absl::Span<uint8_t> GetRtcpPacketForImmediateSend( 218 Clock::time_point send_time, 219 absl::Span<uint8_t> buffer) final; 220 absl::Span<uint8_t> GetRtpPacketForImmediateSend( 221 Clock::time_point send_time, 222 absl::Span<uint8_t> buffer) final; 223 Clock::time_point GetRtpResumeTime() final; 224 225 // CompoundRtcpParser::Client implementation. 226 void OnReceiverReferenceTimeAdvanced(Clock::time_point reference_time) final; 227 void OnReceiverReport(const RtcpReportBlock& receiver_report) final; 228 void OnReceiverIndicatesPictureLoss() final; 229 void OnReceiverCheckpoint(FrameId frame_id, 230 std::chrono::milliseconds playout_delay) final; 231 void OnReceiverHasFrames(std::vector<FrameId> acks) final; 232 void OnReceiverIsMissingPackets(std::vector<PacketNack> nacks) final; 233 234 // Helper to choose which packet to send, from those that have been flagged as 235 // "need to send." Returns a "false" result if nothing needs to be sent. 236 ChosenPacket ChooseNextRtpPacketNeedingSend(); 237 238 // Helper that returns the packet that should be used to kick-start the 239 // Receiver, and the time at which the packet should be sent. Returns a kNever 240 // result if kick-starting is not needed. 241 ChosenPacketAndWhen ChooseKickstartPacket(); 242 243 // Cancels the given frame once it is known to have been fully received (i.e., 244 // based on the ACK feedback from the Receiver in a RTCP packet). This clears 245 // the corresponding entry in |pending_frames_| and notifies the Observer. 246 void CancelPendingFrame(FrameId frame_id); 247 248 // Inline helper to return the slot that would contain the tracking info for 249 // the given |frame_id|. get_slot_for(FrameId frame_id)250 const PendingFrameSlot* get_slot_for(FrameId frame_id) const { 251 return &pending_frames_[(frame_id - FrameId::first()) % 252 pending_frames_.size()]; 253 } get_slot_for(FrameId frame_id)254 PendingFrameSlot* get_slot_for(FrameId frame_id) { 255 return &pending_frames_[(frame_id - FrameId::first()) % 256 pending_frames_.size()]; 257 } 258 259 const SessionConfig config_; 260 SenderPacketRouter* const packet_router_; 261 RtcpSession rtcp_session_; 262 CompoundRtcpParser rtcp_parser_; 263 SenderReportBuilder sender_report_builder_; 264 RtpPacketizer rtp_packetizer_; 265 const int rtp_timebase_; 266 FrameCrypto crypto_; 267 268 // Ring buffer of PendingFrameSlots. The frame having FrameId x will always 269 // be slotted at position x % pending_frames_.size(). Use get_slot_for() to 270 // access the correct slot for a given FrameId. 271 std::array<PendingFrameSlot, kMaxUnackedFrames> pending_frames_{}; 272 273 // A count of the number of frames in-flight (i.e., the number of active 274 // entries in |pending_frames_|). 275 int num_frames_in_flight_ = 0; 276 277 // The ID of the last frame enqueued. 278 FrameId last_enqueued_frame_id_ = FrameId::leader(); 279 280 // Indicates that all of the packets for all frames up to and including this 281 // FrameId have been successfully received (or otherwise do not need to be 282 // re-transmitted). 283 FrameId checkpoint_frame_id_ = FrameId::leader(); 284 285 // The ID of the latest frame the Receiver seems to be aware of. 286 FrameId latest_expected_frame_id_ = FrameId::leader(); 287 288 // The target playout delay for the last-enqueued frame. This is auto-updated 289 // when a frame is enqueued that changes the delay. 290 std::chrono::milliseconds target_playout_delay_; 291 FrameId playout_delay_change_at_frame_id_ = FrameId::first(); 292 293 // The exact arrival time of the last RTCP packet. 294 Clock::time_point rtcp_packet_arrival_time_ = SenderPacketRouter::kNever; 295 296 // The near-term average round trip time. This is updated with each Sender 297 // Report → Receiver Report round trip. This is initially zero, indicating the 298 // round trip time has not been measured yet. 299 Clock::duration round_trip_time_{0}; 300 301 // Maintain current stats in a Sender Report that is ready for sending at any 302 // time. This includes up-to-date lip-sync information, and packet and byte 303 // count stats. 304 RtcpSenderReport pending_sender_report_; 305 306 // These are used to determine whether a key frame needs to be sent to the 307 // Receiver. When the Receiver provides a picture loss notification, the 308 // current checkpoint frame ID is stored in |picture_lost_at_frame_id_|. Then, 309 // while |last_enqueued_key_frame_id_| is less than or equal to 310 // |picture_lost_at_frame_id_|, the Sender knows it still needs to send a key 311 // frame to resolve the picture loss condition. In all other cases, the 312 // Receiver is either in a good state or is in the process of receiving the 313 // key frame that will make that happen. 314 FrameId picture_lost_at_frame_id_ = FrameId::leader(); 315 FrameId last_enqueued_key_frame_id_ = FrameId::leader(); 316 317 // The current observer (optional). 318 Observer* observer_ = nullptr; 319 }; 320 321 } // namespace cast 322 } // namespace openscreen 323 324 #endif // CAST_STREAMING_SENDER_H_ 325