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