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     virtual ~Client();
41 
42     // Called when a Receiver Reference Time Report has been parsed.
43     virtual void OnReceiverReferenceTimeAdvanced(
44         Clock::time_point reference_time);
45 
46     // Called when a Receiver Report with a Report Block has been parsed.
47     virtual void OnReceiverReport(const RtcpReportBlock& receiver_report);
48 
49     // Called when the Receiver has encountered an unrecoverable error in
50     // decoding the data. The Sender should provide a key frame as soon as
51     // possible.
52     virtual void OnReceiverIndicatesPictureLoss();
53 
54     // Called when the Receiver indicates that all of the packets for all frames
55     // up to and including |frame_id| have been successfully received (or
56     // otherwise do not need to be re-transmitted). The |playout_delay| is the
57     // Receiver's current end-to-end target playout delay setting, which should
58     // reflect any changes the Sender has made by using the "Cast Adaptive
59     // Latency Extension" in RTP packets.
60     virtual void OnReceiverCheckpoint(FrameId frame_id,
61                                       std::chrono::milliseconds playout_delay);
62 
63     // Called to indicate the Receiver has successfully received all of the
64     // packets for each of the given |acks|. The argument's elements are in
65     // monotonically increasing order.
66     virtual void OnReceiverHasFrames(std::vector<FrameId> acks);
67 
68     // Called to indicate the Receiver is missing certain specific packets for
69     // certain specific frames. Any elements where the packet_id is
70     // kAllPacketsLost indicates that all the packets are missing for a frame.
71     // The argument's elements are in monotonically increasing order.
72     virtual void OnReceiverIsMissingPackets(std::vector<PacketNack> nacks);
73   };
74 
75   // |session| and |client| must be non-null and must outlive the
76   // CompoundRtcpParser instance.
77   CompoundRtcpParser(RtcpSession* session, Client* client);
78   ~CompoundRtcpParser();
79 
80   // Parses the packet, invoking the Client callback methods when appropriate.
81   // Returns true if the |packet| was well-formed, or false if it was corrupt.
82   // Note that none of the Client callback methods will be invoked until a
83   // packet is known to be well-formed.
84   //
85   // |max_feedback_frame_id| is the maximum-valued FrameId that could possibly
86   // be ACKnowledged by the Receiver, if there is Cast Feedback in the |packet|.
87   // This is needed for expanding truncated frame IDs correctly.
88   bool Parse(absl::Span<const uint8_t> packet, FrameId max_feedback_frame_id);
89 
90  private:
91   // These return true if the input was well-formed, and false if it was
92   // invalid/corrupt. The true/false value does NOT indicate whether the data
93   // contained within was ignored. Output arguments are only modified if the
94   // input contained the relevant field(s).
95   bool ParseReceiverReport(absl::Span<const uint8_t> in,
96                            int num_report_blocks,
97                            absl::optional<RtcpReportBlock>* receiver_report);
98   bool ParseFeedback(absl::Span<const uint8_t> in,
99                      FrameId max_feedback_frame_id,
100                      FrameId* checkpoint_frame_id,
101                      std::chrono::milliseconds* target_playout_delay,
102                      std::vector<FrameId>* received_frames,
103                      std::vector<PacketNack>* packet_nacks);
104   bool ParseExtendedReports(absl::Span<const uint8_t> in,
105                             Clock::time_point* receiver_reference_time);
106   bool ParsePictureLossIndicator(absl::Span<const uint8_t> in,
107                                  bool* picture_loss_indicator);
108 
109   RtcpSession* const session_;
110   Client* const client_;
111 
112   // Tracks the latest timestamp seen from any Receiver Reference Time Report,
113   // and uses this to ignore stale RTCP packets that arrived out-of-order and/or
114   // late from the network.
115   Clock::time_point latest_receiver_timestamp_;
116 };
117 
118 }  // namespace cast
119 }  // namespace openscreen
120 
121 #endif  // CAST_STREAMING_COMPOUND_RTCP_PARSER_H_
122