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