xref: /aosp_15_r20/external/openscreen/cast/streaming/receiver.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_RECEIVER_H_
6*3f982cf4SFabien Sanglard #define CAST_STREAMING_RECEIVER_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 <memory>
13*3f982cf4SFabien Sanglard #include <utility>
14*3f982cf4SFabien Sanglard #include <vector>
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
17*3f982cf4SFabien Sanglard #include "absl/types/span.h"
18*3f982cf4SFabien Sanglard #include "cast/streaming/clock_drift_smoother.h"
19*3f982cf4SFabien Sanglard #include "cast/streaming/compound_rtcp_builder.h"
20*3f982cf4SFabien Sanglard #include "cast/streaming/environment.h"
21*3f982cf4SFabien Sanglard #include "cast/streaming/frame_collector.h"
22*3f982cf4SFabien Sanglard #include "cast/streaming/frame_id.h"
23*3f982cf4SFabien Sanglard #include "cast/streaming/packet_receive_stats_tracker.h"
24*3f982cf4SFabien Sanglard #include "cast/streaming/receiver_base.h"
25*3f982cf4SFabien Sanglard #include "cast/streaming/rtcp_common.h"
26*3f982cf4SFabien Sanglard #include "cast/streaming/rtcp_session.h"
27*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_packet_parser.h"
28*3f982cf4SFabien Sanglard #include "cast/streaming/sender_report_parser.h"
29*3f982cf4SFabien Sanglard #include "cast/streaming/session_config.h"
30*3f982cf4SFabien Sanglard #include "cast/streaming/ssrc.h"
31*3f982cf4SFabien Sanglard #include "platform/api/time.h"
32*3f982cf4SFabien Sanglard #include "util/alarm.h"
33*3f982cf4SFabien Sanglard 
34*3f982cf4SFabien Sanglard namespace openscreen {
35*3f982cf4SFabien Sanglard namespace cast {
36*3f982cf4SFabien Sanglard 
37*3f982cf4SFabien Sanglard struct EncodedFrame;
38*3f982cf4SFabien Sanglard class ReceiverPacketRouter;
39*3f982cf4SFabien Sanglard 
40*3f982cf4SFabien Sanglard // The Cast Streaming Receiver, a peer corresponding to some Cast Streaming
41*3f982cf4SFabien Sanglard // Sender at the other end of a network link.
42*3f982cf4SFabien Sanglard //
43*3f982cf4SFabien Sanglard // Cast Streaming is a transport protocol which divides up the frames for one
44*3f982cf4SFabien Sanglard // media stream (e.g., audio or video) into multiple RTP packets containing an
45*3f982cf4SFabien Sanglard // encrypted payload. The Receiver is the peer responsible for collecting the
46*3f982cf4SFabien Sanglard // RTP packets, decrypting the payload, and re-assembling a frame that can be
47*3f982cf4SFabien Sanglard // passed to a decoder and played out.
48*3f982cf4SFabien Sanglard //
49*3f982cf4SFabien Sanglard // A Sender ↔ Receiver pair is used to transport each media stream. Typically,
50*3f982cf4SFabien Sanglard // there are two pairs in a normal system, one for the audio stream and one for
51*3f982cf4SFabien Sanglard // video stream. A local player is responsible for synchronizing the playout of
52*3f982cf4SFabien Sanglard // the frames of each stream to achieve lip-sync. See the discussion in
53*3f982cf4SFabien Sanglard // encoded_frame.h for how the |reference_time| and |rtp_timestamp| of the
54*3f982cf4SFabien Sanglard // EncodedFrames are used to achieve this.
55*3f982cf4SFabien Sanglard //
56*3f982cf4SFabien Sanglard // See the Receiver Demo app for a reference implementation that both shows and
57*3f982cf4SFabien Sanglard // explains how Receivers are properly configured and started, integrated with a
58*3f982cf4SFabien Sanglard // decoder, and the resulting decoded media is played out. Also, here is a
59*3f982cf4SFabien Sanglard // general usage example:
60*3f982cf4SFabien Sanglard //
61*3f982cf4SFabien Sanglard //   class MyPlayer : public openscreen::cast::Receiver::Consumer {
62*3f982cf4SFabien Sanglard //    public:
63*3f982cf4SFabien Sanglard //     explicit MyPlayer(Receiver* receiver) : receiver_(receiver) {
64*3f982cf4SFabien Sanglard //       recevier_->SetPlayerProcessingTime(std::chrono::milliseconds(10));
65*3f982cf4SFabien Sanglard //       receiver_->SetConsumer(this);
66*3f982cf4SFabien Sanglard //     }
67*3f982cf4SFabien Sanglard //
68*3f982cf4SFabien Sanglard //     ~MyPlayer() override {
69*3f982cf4SFabien Sanglard //       receiver_->SetConsumer(nullptr);
70*3f982cf4SFabien Sanglard //     }
71*3f982cf4SFabien Sanglard //
72*3f982cf4SFabien Sanglard //    private:
73*3f982cf4SFabien Sanglard //     // Receiver::Consumer implementation.
74*3f982cf4SFabien Sanglard //     void OnFramesReady(int next_frame_buffer_size) override {
75*3f982cf4SFabien Sanglard //       std::vector<uint8_t> buffer;
76*3f982cf4SFabien Sanglard //       buffer.resize(next_frame_buffer_size);
77*3f982cf4SFabien Sanglard //       openscreen::cast::EncodedFrame encoded_frame =
78*3f982cf4SFabien Sanglard //           receiver_->ConsumeNextFrame(absl::Span<uint8_t>(buffer));
79*3f982cf4SFabien Sanglard //
80*3f982cf4SFabien Sanglard //       display_.RenderFrame(decoder_.DecodeFrame(encoded_frame.data));
81*3f982cf4SFabien Sanglard //
82*3f982cf4SFabien Sanglard //       // Note: An implementation could call receiver_->AdvanceToNextFrame()
83*3f982cf4SFabien Sanglard //       // and receiver_->ConsumeNextFrame() in a loop here, to consume all the
84*3f982cf4SFabien Sanglard //       // remaining frames that are ready.
85*3f982cf4SFabien Sanglard //     }
86*3f982cf4SFabien Sanglard //
87*3f982cf4SFabien Sanglard //     Receiver* const receiver_;
88*3f982cf4SFabien Sanglard //     MyDecoder decoder_;
89*3f982cf4SFabien Sanglard //     MyDisplay display_;
90*3f982cf4SFabien Sanglard //   };
91*3f982cf4SFabien Sanglard //
92*3f982cf4SFabien Sanglard // Internally, a queue of complete and partially-received frames is maintained.
93*3f982cf4SFabien Sanglard // The queue is a circular queue of FrameCollectors that each maintain the
94*3f982cf4SFabien Sanglard // individual receive state of each in-flight frame. There are three conceptual
95*3f982cf4SFabien Sanglard // "pointers" that indicate what assumptions and operations are made on certain
96*3f982cf4SFabien Sanglard // ranges of frames in the queue:
97*3f982cf4SFabien Sanglard //
98*3f982cf4SFabien Sanglard //   1. Latest Frame Expected: The FrameId of the latest frame whose existence
99*3f982cf4SFabien Sanglard //      is known to this Receiver. This is the highest FrameId seen in any
100*3f982cf4SFabien Sanglard //      successfully-parsed RTP packet.
101*3f982cf4SFabien Sanglard //   2. Checkpoint Frame: Indicates that all of the RTP packets for all frames
102*3f982cf4SFabien Sanglard //      up to and including the one having this FrameId have been successfully
103*3f982cf4SFabien Sanglard //      received and processed.
104*3f982cf4SFabien Sanglard //   3. Last Frame Consumed: The FrameId of last frame consumed (see
105*3f982cf4SFabien Sanglard //      ConsumeNextFrame()). Once a frame is consumed, all internal resources
106*3f982cf4SFabien Sanglard //      related to the frame can be freed and/or re-used for later frames.
107*3f982cf4SFabien Sanglard class Receiver : public ReceiverBase {
108*3f982cf4SFabien Sanglard  public:
109*3f982cf4SFabien Sanglard   using ReceiverBase::Consumer;
110*3f982cf4SFabien Sanglard 
111*3f982cf4SFabien Sanglard   // Constructs a Receiver that attaches to the given |environment| and
112*3f982cf4SFabien Sanglard   // |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).
116*3f982cf4SFabien Sanglard   Receiver(Environment* environment,
117*3f982cf4SFabien Sanglard            ReceiverPacketRouter* packet_router,
118*3f982cf4SFabien Sanglard            SessionConfig config);
119*3f982cf4SFabien Sanglard   ~Receiver() override;
120*3f982cf4SFabien Sanglard 
121*3f982cf4SFabien Sanglard   // ReceiverBase overrides.
122*3f982cf4SFabien Sanglard   const SessionConfig& config() const override;
123*3f982cf4SFabien Sanglard   int rtp_timebase() const override;
124*3f982cf4SFabien Sanglard   Ssrc ssrc() const override;
125*3f982cf4SFabien Sanglard   void SetConsumer(Consumer* consumer) override;
126*3f982cf4SFabien Sanglard   void SetPlayerProcessingTime(Clock::duration needed_time) override;
127*3f982cf4SFabien Sanglard   void RequestKeyFrame() override;
128*3f982cf4SFabien Sanglard   int AdvanceToNextFrame() override;
129*3f982cf4SFabien Sanglard   EncodedFrame ConsumeNextFrame(absl::Span<uint8_t> buffer) override;
130*3f982cf4SFabien Sanglard 
131*3f982cf4SFabien Sanglard   // Allows setting picture loss indication for testing. In production, this
132*3f982cf4SFabien Sanglard   // should be done using the config.
SetPliEnabledForTesting(bool is_pli_enabled)133*3f982cf4SFabien Sanglard   void SetPliEnabledForTesting(bool is_pli_enabled) {
134*3f982cf4SFabien Sanglard     is_pli_enabled_ = is_pli_enabled;
135*3f982cf4SFabien Sanglard   }
136*3f982cf4SFabien Sanglard 
137*3f982cf4SFabien Sanglard   // The default "player processing time" amount. See SetPlayerProcessingTime().
138*3f982cf4SFabien Sanglard   static constexpr std::chrono::milliseconds kDefaultPlayerProcessingTime =
139*3f982cf4SFabien Sanglard       ReceiverBase::kDefaultPlayerProcessingTime;
140*3f982cf4SFabien Sanglard 
141*3f982cf4SFabien Sanglard   // Returned by AdvanceToNextFrame() when there are no frames currently ready
142*3f982cf4SFabien Sanglard   // for consumption.
143*3f982cf4SFabien Sanglard   static constexpr int kNoFramesReady = ReceiverBase::kNoFramesReady;
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard  protected:
146*3f982cf4SFabien Sanglard   friend class ReceiverPacketRouter;
147*3f982cf4SFabien Sanglard 
148*3f982cf4SFabien Sanglard   // Called by ReceiverPacketRouter to provide this Receiver with what looks
149*3f982cf4SFabien Sanglard   // like a RTP/RTCP packet meant for it specifically (among other Receivers).
150*3f982cf4SFabien Sanglard   void OnReceivedRtpPacket(Clock::time_point arrival_time,
151*3f982cf4SFabien Sanglard                            std::vector<uint8_t> packet);
152*3f982cf4SFabien Sanglard   void OnReceivedRtcpPacket(Clock::time_point arrival_time,
153*3f982cf4SFabien Sanglard                             std::vector<uint8_t> packet);
154*3f982cf4SFabien Sanglard 
155*3f982cf4SFabien Sanglard  private:
156*3f982cf4SFabien Sanglard   // An entry in the circular queue (see |pending_frames_|).
157*3f982cf4SFabien Sanglard   struct PendingFrame {
158*3f982cf4SFabien Sanglard     FrameCollector collector;
159*3f982cf4SFabien Sanglard 
160*3f982cf4SFabien Sanglard     // The Receiver's [local] Clock time when this frame was originally captured
161*3f982cf4SFabien Sanglard     // at the Sender. This is computed and assigned when the RTP packet with ID
162*3f982cf4SFabien Sanglard     // 0 is processed. Add the target playout delay to this to get the target
163*3f982cf4SFabien Sanglard     // playout time.
164*3f982cf4SFabien Sanglard     absl::optional<Clock::time_point> estimated_capture_time;
165*3f982cf4SFabien Sanglard 
166*3f982cf4SFabien Sanglard     PendingFrame();
167*3f982cf4SFabien Sanglard     ~PendingFrame();
168*3f982cf4SFabien Sanglard 
169*3f982cf4SFabien Sanglard     // Reset this entry to its initial state, freeing resources.
170*3f982cf4SFabien Sanglard     void Reset();
171*3f982cf4SFabien Sanglard   };
172*3f982cf4SFabien Sanglard 
173*3f982cf4SFabien Sanglard   // Get/Set the checkpoint FrameId. This indicates that all of the packets for
174*3f982cf4SFabien Sanglard   // all frames up to and including this FrameId have been successfully received
175*3f982cf4SFabien Sanglard   // (or otherwise do not need to be re-transmitted).
checkpoint_frame()176*3f982cf4SFabien Sanglard   FrameId checkpoint_frame() const { return rtcp_builder_.checkpoint_frame(); }
set_checkpoint_frame(FrameId frame_id)177*3f982cf4SFabien Sanglard   void set_checkpoint_frame(FrameId frame_id) {
178*3f982cf4SFabien Sanglard     rtcp_builder_.SetCheckpointFrame(frame_id);
179*3f982cf4SFabien Sanglard   }
180*3f982cf4SFabien Sanglard 
181*3f982cf4SFabien Sanglard   // Send an RTCP packet to the Sender immediately, to acknowledge the complete
182*3f982cf4SFabien Sanglard   // reception of one or more additional frames, to reply to a Sender Report, or
183*3f982cf4SFabien Sanglard   // to request re-transmits. Calling this also schedules additional RTCP
184*3f982cf4SFabien Sanglard   // packets to be sent periodically for the life of this Receiver.
185*3f982cf4SFabien Sanglard   void SendRtcp();
186*3f982cf4SFabien Sanglard 
187*3f982cf4SFabien Sanglard   // Helpers to map the given |frame_id| to the element in the |pending_frames_|
188*3f982cf4SFabien Sanglard   // circular queue. There are both const and non-const versions, but neither
189*3f982cf4SFabien Sanglard   // mutate any state (i.e., they are just look-ups).
190*3f982cf4SFabien Sanglard   const PendingFrame& GetQueueEntry(FrameId frame_id) const;
191*3f982cf4SFabien Sanglard   PendingFrame& GetQueueEntry(FrameId frame_id);
192*3f982cf4SFabien Sanglard 
193*3f982cf4SFabien Sanglard   // Record that the target playout delay has changed starting with the given
194*3f982cf4SFabien Sanglard   // FrameId.
195*3f982cf4SFabien Sanglard   void RecordNewTargetPlayoutDelay(FrameId as_of_frame,
196*3f982cf4SFabien Sanglard                                    std::chrono::milliseconds delay);
197*3f982cf4SFabien Sanglard 
198*3f982cf4SFabien Sanglard   // Examine the known target playout delay changes to determine what setting is
199*3f982cf4SFabien Sanglard   // in-effect for the given frame.
200*3f982cf4SFabien Sanglard   std::chrono::milliseconds ResolveTargetPlayoutDelay(FrameId frame_id) const;
201*3f982cf4SFabien Sanglard 
202*3f982cf4SFabien Sanglard   // Called to move the checkpoint forward. This scans the queue, starting from
203*3f982cf4SFabien Sanglard   // |new_checkpoint|, to find the latest in a contiguous sequence of completed
204*3f982cf4SFabien Sanglard   // frames. Then, it records that frame as the new checkpoint, and immediately
205*3f982cf4SFabien Sanglard   // sends a feedback RTCP packet to the Sender.
206*3f982cf4SFabien Sanglard   void AdvanceCheckpoint(FrameId new_checkpoint);
207*3f982cf4SFabien Sanglard 
208*3f982cf4SFabien Sanglard   // Helper to force-drop all frames before |first_kept_frame|, even if they
209*3f982cf4SFabien Sanglard   // were never consumed. This will also auto-cancel frames that were never
210*3f982cf4SFabien Sanglard   // completely received, artificially moving the checkpoint forward, and
211*3f982cf4SFabien Sanglard   // notifying the Sender of that. The caller of this method is responsible for
212*3f982cf4SFabien Sanglard   // making sure that frame data dependencies will not be broken by dropping the
213*3f982cf4SFabien Sanglard   // frames.
214*3f982cf4SFabien Sanglard   void DropAllFramesBefore(FrameId first_kept_frame);
215*3f982cf4SFabien Sanglard 
216*3f982cf4SFabien Sanglard   // Sets the |consumption_alarm_| to check whether any frames are ready,
217*3f982cf4SFabien Sanglard   // including possibly skipping over late frames in order to make not-yet-late
218*3f982cf4SFabien Sanglard   // frames become ready. The default argument value means "without delay."
219*3f982cf4SFabien Sanglard   void ScheduleFrameReadyCheck(Clock::time_point when = Alarm::kImmediately);
220*3f982cf4SFabien Sanglard 
221*3f982cf4SFabien Sanglard   const ClockNowFunctionPtr now_;
222*3f982cf4SFabien Sanglard   ReceiverPacketRouter* const packet_router_;
223*3f982cf4SFabien Sanglard   const SessionConfig config_;
224*3f982cf4SFabien Sanglard   RtcpSession rtcp_session_;
225*3f982cf4SFabien Sanglard   SenderReportParser rtcp_parser_;
226*3f982cf4SFabien Sanglard   CompoundRtcpBuilder rtcp_builder_;
227*3f982cf4SFabien Sanglard   PacketReceiveStatsTracker stats_tracker_;  // Tracks transmission stats.
228*3f982cf4SFabien Sanglard   RtpPacketParser rtp_parser_;
229*3f982cf4SFabien Sanglard   const int rtp_timebase_;    // RTP timestamp ticks per second.
230*3f982cf4SFabien Sanglard   const FrameCrypto crypto_;  // Decrypts assembled frames.
231*3f982cf4SFabien Sanglard   bool is_pli_enabled_;       // Whether picture loss indication is enabled.
232*3f982cf4SFabien Sanglard 
233*3f982cf4SFabien Sanglard   // Buffer for serializing/sending RTCP packets.
234*3f982cf4SFabien Sanglard   const int rtcp_buffer_capacity_;
235*3f982cf4SFabien Sanglard   const std::unique_ptr<uint8_t[]> rtcp_buffer_;
236*3f982cf4SFabien Sanglard 
237*3f982cf4SFabien Sanglard   // Schedules tasks to ensure RTCP reports are sent within a bounded interval.
238*3f982cf4SFabien Sanglard   // Not scheduled until after this Receiver has processed the first packet from
239*3f982cf4SFabien Sanglard   // the Sender.
240*3f982cf4SFabien Sanglard   Alarm rtcp_alarm_;
241*3f982cf4SFabien Sanglard   Clock::time_point last_rtcp_send_time_ = Clock::time_point::min();
242*3f982cf4SFabien Sanglard 
243*3f982cf4SFabien Sanglard   // The last Sender Report received and when the packet containing it had
244*3f982cf4SFabien Sanglard   // arrived. This contains lip-sync timestamps used as part of the calculation
245*3f982cf4SFabien Sanglard   // of playout times for the received frames, as well as ping-pong data bounced
246*3f982cf4SFabien Sanglard   // back to the Sender in the Receiver Reports. It is nullopt until the first
247*3f982cf4SFabien Sanglard   // parseable Sender Report is received.
248*3f982cf4SFabien Sanglard   absl::optional<SenderReportParser::SenderReportWithId> last_sender_report_;
249*3f982cf4SFabien Sanglard   Clock::time_point last_sender_report_arrival_time_;
250*3f982cf4SFabien Sanglard 
251*3f982cf4SFabien Sanglard   // Tracks the offset between the Receiver's [local] clock and the Sender's
252*3f982cf4SFabien Sanglard   // clock. This is invalid until the first Sender Report has been successfully
253*3f982cf4SFabien Sanglard   // processed (i.e., |last_sender_report_| is not nullopt).
254*3f982cf4SFabien Sanglard   ClockDriftSmoother smoothed_clock_offset_;
255*3f982cf4SFabien Sanglard 
256*3f982cf4SFabien Sanglard   // The ID of the latest frame whose existence is known to this Receiver. This
257*3f982cf4SFabien Sanglard   // value must always be greater than or equal to |checkpoint_frame()|.
258*3f982cf4SFabien Sanglard   FrameId latest_frame_expected_ = FrameId::leader();
259*3f982cf4SFabien Sanglard 
260*3f982cf4SFabien Sanglard   // The ID of the last frame consumed. This value must always be less than or
261*3f982cf4SFabien Sanglard   // equal to |checkpoint_frame()|, since it's impossible to consume incomplete
262*3f982cf4SFabien Sanglard   // frames!
263*3f982cf4SFabien Sanglard   FrameId last_frame_consumed_ = FrameId::leader();
264*3f982cf4SFabien Sanglard 
265*3f982cf4SFabien Sanglard   // The ID of the latest key frame known to be in-flight. This is used by
266*3f982cf4SFabien Sanglard   // RequestKeyFrame() to ensure the PLI condition doesn't get set again until
267*3f982cf4SFabien Sanglard   // after the consumer has seen a key frame that would clear the condition.
268*3f982cf4SFabien Sanglard   FrameId last_key_frame_received_;
269*3f982cf4SFabien Sanglard 
270*3f982cf4SFabien Sanglard   // The frame queue (circular), which tracks which frames are in-flight, stores
271*3f982cf4SFabien Sanglard   // data for partially-received frames, and holds onto completed frames until
272*3f982cf4SFabien Sanglard   // the consumer consumes them.
273*3f982cf4SFabien Sanglard   //
274*3f982cf4SFabien Sanglard   // Use GetQueueEntry() to access a slot. The currently-active slots are those
275*3f982cf4SFabien Sanglard   // for the frames after |last_frame_consumed_| and up-to/including
276*3f982cf4SFabien Sanglard   // |latest_frame_expected_|.
277*3f982cf4SFabien Sanglard   std::array<PendingFrame, kMaxUnackedFrames> pending_frames_{};
278*3f982cf4SFabien Sanglard 
279*3f982cf4SFabien Sanglard   // Tracks the recent changes to the target playout delay, which is controlled
280*3f982cf4SFabien Sanglard   // by the Sender. The FrameId indicates the first frame where a new delay
281*3f982cf4SFabien Sanglard   // setting takes effect. This vector is never empty, is kept sorted, and is
282*3f982cf4SFabien Sanglard   // pruned to remain as small as possible.
283*3f982cf4SFabien Sanglard   //
284*3f982cf4SFabien Sanglard   // The target playout delay is the amount of time between a frame's
285*3f982cf4SFabien Sanglard   // capture/recording on the Sender and when it should be played-out at the
286*3f982cf4SFabien Sanglard   // Receiver.
287*3f982cf4SFabien Sanglard   std::vector<std::pair<FrameId, std::chrono::milliseconds>>
288*3f982cf4SFabien Sanglard       playout_delay_changes_;
289*3f982cf4SFabien Sanglard 
290*3f982cf4SFabien Sanglard   // The consumer to notify when there are one or more frames completed and
291*3f982cf4SFabien Sanglard   // ready to be consumed.
292*3f982cf4SFabien Sanglard   Consumer* consumer_ = nullptr;
293*3f982cf4SFabien Sanglard 
294*3f982cf4SFabien Sanglard   // The additional time needed to decode/play-out each frame after being
295*3f982cf4SFabien Sanglard   // consumed from this Receiver.
296*3f982cf4SFabien Sanglard   Clock::duration player_processing_time_ = kDefaultPlayerProcessingTime;
297*3f982cf4SFabien Sanglard 
298*3f982cf4SFabien Sanglard   // Scheduled to check whether there are frames ready and, if there are, to
299*3f982cf4SFabien Sanglard   // notify the Consumer via OnFramesReady().
300*3f982cf4SFabien Sanglard   Alarm consumption_alarm_;
301*3f982cf4SFabien Sanglard 
302*3f982cf4SFabien Sanglard   // The interval between sending ACK/NACK feedback RTCP messages while
303*3f982cf4SFabien Sanglard   // incomplete frames exist in the queue.
304*3f982cf4SFabien Sanglard   //
305*3f982cf4SFabien Sanglard   // TODO(jophba): This should be a function of the current target playout
306*3f982cf4SFabien Sanglard   // delay, similar to the Sender's kickstart interval logic.
307*3f982cf4SFabien Sanglard   static constexpr std::chrono::milliseconds kNackFeedbackInterval{30};
308*3f982cf4SFabien Sanglard };
309*3f982cf4SFabien Sanglard 
310*3f982cf4SFabien Sanglard }  // namespace cast
311*3f982cf4SFabien Sanglard }  // namespace openscreen
312*3f982cf4SFabien Sanglard 
313*3f982cf4SFabien Sanglard #endif  // CAST_STREAMING_RECEIVER_H_
314