• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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