• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_COMPOUND_RTCP_PARSER_H_
6 #define CAST_STREAMING_COMPOUND_RTCP_PARSER_H_
7 
8 #include <chrono>
9 #include <vector>
10 
11 #include "absl/types/optional.h"
12 #include "absl/types/span.h"
13 #include "cast/streaming/frame_id.h"
14 #include "cast/streaming/rtcp_common.h"
15 #include "cast/streaming/rtp_defines.h"
16 
17 namespace openscreen {
18 namespace cast {
19 
20 class RtcpSession;
21 
22 // Parses compound RTCP packets from a Receiver, invoking client callbacks when
23 // information of interest to a Sender (in the current process) is encountered.
24 class CompoundRtcpParser {
25  public:
26   // Callback interface used while parsing RTCP packets of interest to a Sender.
27   // The implementation must take into account:
28   //
29   //   1. Some/All of the data could be stale, as it only reflects the state of
30   //      the Receiver at the time the packet was generated. A significant
31   //      amount of time may have passed, depending on how long it took the
32   //      packet to reach this local instance over the network.
33   //   2. The data shouldn't necessarily be trusted blindly: Some may be
34   //      inconsistent (e.g., the same frame being ACKed and NACKed; or a frame
35   //      that has not been sent yet is being NACKed). While that would indicate
36   //      a badly-behaving Receiver, the Sender should be robust to such things.
37   class Client {
38    public:
39     Client();
40 
41     // Called when a Receiver Reference Time Report has been parsed.
42     virtual void OnReceiverReferenceTimeAdvanced(
43         Clock::time_point reference_time);
44 
45     // Called when a Receiver Report with a Report Block has been parsed.
46     virtual void OnReceiverReport(const RtcpReportBlock& receiver_report);
47 
48     // Called when the Receiver has encountered an unrecoverable error in
49     // decoding the data. The Sender should provide a key frame as soon as
50     // possible.
51     virtual void OnReceiverIndicatesPictureLoss();
52 
53     // Called when the Receiver indicates that all of the packets for all frames
54     // up to and including |frame_id| have been successfully received (or
55     // otherwise do not need to be re-transmitted). The |playout_delay| is the
56     // Receiver's current end-to-end target playout delay setting, which should
57     // reflect any changes the Sender has made by using the "Cast Adaptive
58     // Latency Extension" in RTP packets.
59     virtual void OnReceiverCheckpoint(FrameId frame_id,
60                                       std::chrono::milliseconds playout_delay);
61 
62     // Called to indicate the Receiver has successfully received all of the
63     // packets for each of the given |acks|. The argument's elements are in
64     // monotonically increasing order.
65     virtual void OnReceiverHasFrames(std::vector<FrameId> acks);
66 
67     // Called to indicate the Receiver is missing certain specific packets for
68     // certain specific frames. Any elements where the packet_id is
69     // kAllPacketsLost indicates that all the packets are missing for a frame.
70     // The argument's elements are in monotonically increasing order.
71     virtual void OnReceiverIsMissingPackets(std::vector<PacketNack> nacks);
72 
73    protected:
74     virtual ~Client();
75   };
76 
77   // |session| and |client| must be non-null and must outlive the
78   // CompoundRtcpParser instance.
79   CompoundRtcpParser(RtcpSession* session, Client* client);
80   ~CompoundRtcpParser();
81 
82   // Parses the packet, invoking the Client callback methods when appropriate.
83   // Returns true if the |packet| was well-formed, or false if it was corrupt.
84   // Note that none of the Client callback methods will be invoked until a
85   // packet is known to be well-formed.
86   //
87   // |max_feedback_frame_id| is the maximum-valued FrameId that could possibly
88   // be ACKnowledged by the Receiver, if there is Cast Feedback in the |packet|.
89   // This is needed for expanding truncated frame IDs correctly.
90   bool Parse(absl::Span<const uint8_t> packet, FrameId max_feedback_frame_id);
91 
92  private:
93   // These return true if the input was well-formed, and false if it was
94   // invalid/corrupt. The true/false value does NOT indicate whether the data
95   // contained within was ignored. Output arguments are only modified if the
96   // input contained the relevant field(s).
97   bool ParseReceiverReport(absl::Span<const uint8_t> in,
98                            int num_report_blocks,
99                            absl::optional<RtcpReportBlock>* receiver_report);
100   bool ParseFeedback(absl::Span<const uint8_t> in,
101                      FrameId max_feedback_frame_id,
102                      FrameId* checkpoint_frame_id,
103                      std::chrono::milliseconds* target_playout_delay,
104                      std::vector<FrameId>* received_frames,
105                      std::vector<PacketNack>* packet_nacks);
106   bool ParseExtendedReports(absl::Span<const uint8_t> in,
107                             Clock::time_point* receiver_reference_time);
108   bool ParsePictureLossIndicator(absl::Span<const uint8_t> in,
109                                  bool* picture_loss_indicator);
110 
111   RtcpSession* const session_;
112   Client* const client_;
113 
114   // Tracks the latest timestamp seen from any Receiver Reference Time Report,
115   // and uses this to ignore stale RTCP packets that arrived out-of-order and/or
116   // late from the network.
117   Clock::time_point latest_receiver_timestamp_;
118 };
119 
120 }  // namespace cast
121 }  // namespace openscreen
122 
123 #endif  // CAST_STREAMING_COMPOUND_RTCP_PARSER_H_
124