OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ | 5 #ifndef CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ |
6 #define CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ | 6 #define CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ |
7 | 7 |
| 8 #include <queue> |
| 9 |
8 #include "base/callback_forward.h" | 10 #include "base/callback_forward.h" |
9 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
10 #include "base/time/time.h" | 12 #include "base/time/time.h" |
11 #include "media/cast/cast_config.h" | 13 #include "media/cast/cast_config.h" |
12 #include "media/cast/cast_environment.h" | 14 #include "media/cast/cast_environment.h" |
13 #include "media/cast/net/cast_transport.h" | 15 #include "media/cast/net/cast_transport.h" |
14 #include "media/cast/net/rtcp/rtcp_defines.h" | 16 #include "media/cast/net/rtcp/rtcp_defines.h" |
| 17 #include "media/mojo/interfaces/remoting.mojom.h" |
| 18 #include "mojo/public/cpp/bindings/binding.h" |
| 19 #include "mojo/public/cpp/system/watcher.h" |
15 | 20 |
16 namespace cast { | 21 namespace cast { |
17 | 22 |
18 // RTP sender for a single Cast Remoting RTP stream. The client calls Send() to | 23 // RTP sender for a single Cast Remoting RTP stream. The client calls Send() to |
19 // instruct the sender to transmit the data using a CastTransport. | 24 // instruct the sender to read from a Mojo data pipe and transmit the data using |
| 25 // a CastTransport. This entire class executes on the IO BrowserThread. |
20 // | 26 // |
21 // This class is instantiated and owned by CastTransportHostFilter in response | 27 // This class is instantiated and owned by CastTransportHostFilter in response |
22 // to IPC messages from an extension process to create RTP streams for the media | 28 // to IPC messages from an extension process to create RTP streams for the media |
23 // remoting use case. CastTransportHostFilter is also responsible for destroying | 29 // remoting use case. CastTransportHostFilter is also responsible for destroying |
24 // the instance in response to later IPCs. | 30 // the instance in response to later IPCs. |
25 // | 31 // |
26 // TODO(miu): Mojo service bindings/implementation to read from data pipes will | 32 // The Media Router provider extension controls the entire set-up process: |
27 // be added in a soon-upcoming change. | 33 // First, it uses the cast.streaming APIs to create remoting API streams (which |
28 | 34 // instantiates one or more CastRemotingSenders). Then, it sends a message via |
29 class CastRemotingSender { | 35 // Media Router to a CastRemotingConnector to indicate the bitstream transport |
| 36 // is ready. Finally, CastRemotingConnector calls FindAndBind() to look-up the |
| 37 // CastRemotingSender instances and establish the Mojo bindings and data flows. |
| 38 class CastRemotingSender : public media::mojom::RemotingDataStreamSender { |
30 public: | 39 public: |
31 // |transport| is expected to outlive this class. | 40 // |transport| is expected to outlive this class. |
32 explicit CastRemotingSender( | 41 CastRemotingSender( |
33 scoped_refptr<media::cast::CastEnvironment> cast_environment, | 42 scoped_refptr<media::cast::CastEnvironment> cast_environment, |
34 media::cast::CastTransport* transport, | 43 media::cast::CastTransport* transport, |
35 const media::cast::CastTransportRtpConfig& config); | 44 const media::cast::CastTransportRtpConfig& config); |
36 ~CastRemotingSender(); | 45 ~CastRemotingSender() final; |
| 46 |
| 47 // Look-up a CastRemotingSender instance by its |rtp_stream_id| and then bind |
| 48 // to the given |request|. The client of the RemotingDataStreamSender will |
| 49 // then instruct this CastRemotingSender when to read from the data |pipe| and |
| 50 // send the data to the Cast Receiver. If the bind fails, or an error occurs |
| 51 // reading from the data pipe during later operation, the |error_callback| is |
| 52 // run. |
| 53 // |
| 54 // Threading note: This function is thread-safe, but its internal |
| 55 // implementation runs on the IO BrowserThread. If |error_callback| is run, it |
| 56 // will execute on the thread that called this function. |
| 57 static void FindAndBind(int32_t rtp_stream_id, |
| 58 mojo::ScopedDataPipeConsumerHandle pipe, |
| 59 media::mojom::RemotingDataStreamSenderRequest request, |
| 60 const base::Closure& error_callback); |
37 | 61 |
38 private: | 62 private: |
39 // Friend class for unit tests. | 63 // Friend class for unit tests. |
40 friend class CastRemotingSenderTest; | 64 friend class CastRemotingSenderTest; |
41 | 65 |
42 class RemotingRtcpClient; | 66 class RemotingRtcpClient; |
43 | 67 |
44 // Called to send the serialized frame data. | 68 // media::mojom::RemotingDataStreamSender implementation. ConsumeDataChunk() |
45 void SendFrame(); | 69 // and SendFrame() will push callbacks onto the back of the input queue, and |
| 70 // these may or may not be processed at a later time. It depends on whether |
| 71 // the data pipe has data available or the CastTransport can accept more |
| 72 // frames. CancelInFlightData() is processed immediately, and will cause all |
| 73 // pending operations to discard data when they are processed later. |
| 74 void ConsumeDataChunk(uint32_t offset, uint32_t size, |
| 75 uint32_t total_payload_size) final; |
| 76 void SendFrame() final; |
| 77 void CancelInFlightData() final; |
46 | 78 |
47 // Called to cancel all the in flight frames when seeking happens. | 79 // Attempt to run each pending input operation, popping the head of the input |
48 void CancelFramesInFlight(); | 80 // queue as each operation succeeds. |result| is the result code provided by |
| 81 // the |pipe_watcher_|. |
| 82 void ProcessInputQueue(MojoResult result); |
| 83 |
| 84 // These are called via callbacks run from the input queue. They return false |
| 85 // to indicate a retry attempt should be made later, either after the data |
| 86 // pipe has more data or the CastTransport can accept another frame. |
| 87 bool TryConsumeDataChunk(uint32_t offset, uint32_t size, |
| 88 uint32_t total_payload_size, bool discard_data); |
| 89 bool TrySendFrame(bool discard_data); |
49 | 90 |
50 // These are called to deliver RTCP feedback from the receiver. | 91 // These are called to deliver RTCP feedback from the receiver. |
51 void OnReceivedCastMessage(const media::cast::RtcpCastMessage& cast_feedback); | 92 void OnReceivedCastMessage(const media::cast::RtcpCastMessage& cast_feedback); |
52 void OnReceivedRtt(base::TimeDelta round_trip_time); | 93 void OnReceivedRtt(base::TimeDelta round_trip_time); |
53 | 94 |
54 // Returns the number of frames that were sent but not yet acknowledged. This | 95 // Returns the number of frames that were sent to the CastTransport, but not |
55 // does not account for frames acknowledged out-of-order, and is always a high | 96 // yet acknowledged. This is always a high watermark estimate, as frames may |
56 // watermark estimate. | 97 // have been acknowledged out-of-order. Also, this does not account for any |
| 98 // frames queued-up in input pipeline (i.e., in the Mojo data pipe, nor in |
| 99 // |next_frame_data_|). |
57 int NumberOfFramesInFlight() const; | 100 int NumberOfFramesInFlight() const; |
58 | 101 |
59 // Schedule and execute periodic checks for re-sending packets. If no | 102 // Schedule and execute periodic checks for re-sending packets. If no |
60 // acknowledgements have been received for "too long," CastRemotingSender will | 103 // acknowledgements have been received for "too long," CastRemotingSender will |
61 // speculatively re-send certain packets of an unacked frame to kick-start | 104 // speculatively re-send certain packets of an unacked frame to kick-start |
62 // re-transmission. This is a last resort tactic to prevent the session from | 105 // re-transmission. This is a last resort tactic to prevent the session from |
63 // getting stuck after a long outage. | 106 // getting stuck after a long outage. |
64 void ScheduleNextResendCheck(); | 107 void ScheduleNextResendCheck(); |
65 void ResendCheck(); | 108 void ResendCheck(); |
66 void ResendForKickstart(); | 109 void ResendForKickstart(); |
67 | 110 |
68 void RecordLatestFrameTimestamps(media::cast::FrameId frame_id, | 111 void RecordLatestFrameTimestamps(media::cast::FrameId frame_id, |
69 media::cast::RtpTimeTicks rtp_timestamp); | 112 media::cast::RtpTimeTicks rtp_timestamp); |
70 media::cast::RtpTimeTicks GetRecordedRtpTimestamp( | 113 media::cast::RtpTimeTicks GetRecordedRtpTimestamp( |
71 media::cast::FrameId frame_id) const; | 114 media::cast::FrameId frame_id) const; |
72 | 115 |
73 // Unique identifier for the RTP stream and this CastRemotingSender. | 116 // Unique identifier for the RTP stream and this CastRemotingSender. |
74 const int32_t remoting_stream_id_; | 117 const int32_t rtp_stream_id_; |
75 | 118 |
76 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; | 119 const scoped_refptr<media::cast::CastEnvironment> cast_environment_; |
77 | 120 |
78 // Sends encoded frames over the configured transport (e.g., UDP). It outlives | 121 // Sends encoded frames over the configured transport (e.g., UDP). It outlives |
79 // this class. | 122 // this class. |
80 media::cast::CastTransport* const transport_; | 123 media::cast::CastTransport* const transport_; |
81 | 124 |
82 const uint32_t ssrc_; | 125 const uint32_t ssrc_; |
83 | 126 |
84 const bool is_audio_; | 127 const bool is_audio_; |
85 | 128 |
| 129 // Callback that is run to notify when a fatal error occurs. |
| 130 base::Closure error_callback_; |
| 131 |
| 132 // Mojo data pipe from which to consume data. |
| 133 mojo::ScopedDataPipeConsumerHandle pipe_; |
| 134 |
| 135 // Mojo binding for this instance. Implementation at the other end of the |
| 136 // message pipe uses the RemotingDataStreamSender interface to control when |
| 137 // this CastRemotingSender consumes from |pipe_|. |
| 138 mojo::Binding<RemotingDataStreamSender> binding_; |
| 139 |
86 // This is the maximum delay that the sender should get ack from receiver. | 140 // This is the maximum delay that the sender should get ack from receiver. |
87 // Otherwise, sender will call ResendForKickstart(). | 141 // Otherwise, sender will call ResendForKickstart(). |
88 base::TimeDelta max_ack_delay_; | 142 base::TimeDelta max_ack_delay_; |
89 | 143 |
90 // This is "null" until the first frame is sent. Thereafter, this tracks the | 144 // This is "null" until the first frame is sent. Thereafter, this tracks the |
91 // last time any frame was sent or re-sent. | 145 // last time any frame was sent or re-sent. |
92 base::TimeTicks last_send_time_; | 146 base::TimeTicks last_send_time_; |
93 | 147 |
94 // The ID of the last frame sent. This member is invalid until | 148 // The ID of the last frame sent. This member is invalid until |
95 // |!last_send_time_.is_null()|. | 149 // |!last_send_time_.is_null()|. |
96 media::cast::FrameId last_sent_frame_id_; | 150 media::cast::FrameId last_sent_frame_id_; |
97 | 151 |
98 // The ID of the latest (not necessarily the last) frame that has been | 152 // The ID of the latest (not necessarily the last) frame that has been |
99 // acknowledged. This member is invalid until |!last_send_time_.is_null()|. | 153 // acknowledged. This member is invalid until |!last_send_time_.is_null()|. |
100 media::cast::FrameId latest_acked_frame_id_; | 154 media::cast::FrameId latest_acked_frame_id_; |
101 | 155 |
102 // Counts the number of duplicate ACK that are being received. When this | 156 // Counts the number of duplicate ACK that are being received. When this |
103 // number reaches a threshold, the sender will take this as a sign that the | 157 // number reaches a threshold, the sender will take this as a sign that the |
104 // receiver hasn't yet received the first packet of the next frame. In this | 158 // receiver hasn't yet received the first packet of the next frame. In this |
105 // case, CastRemotingSender will trigger a re-send of the next frame. | 159 // case, CastRemotingSender will trigger a re-send of the next frame. |
106 int duplicate_ack_counter_; | 160 int duplicate_ack_counter_; |
107 | 161 |
108 // The most recently measured round trip time. | 162 // The most recently measured round trip time. |
109 base::TimeDelta current_round_trip_time_; | 163 base::TimeDelta current_round_trip_time_; |
110 | 164 |
111 // The next frame's payload data. Populated by one or more calls to | 165 // The next frame's payload data. Populated by one or more calls to |
112 // ConsumeDataChunk(). | 166 // ConsumeDataChunk(). |
113 // TODO(miu): To be implemented in soon upcoming change. | |
114 std::string next_frame_data_; | 167 std::string next_frame_data_; |
115 | 168 |
116 // Ring buffer to keep track of recent frame RTP timestamps. This should | 169 // Ring buffer to keep track of recent frame RTP timestamps. This should |
117 // only be accessed through the Record/GetXX() methods. The index into this | 170 // only be accessed through the Record/GetXX() methods. The index into this |
118 // ring buffer is the lower 8 bits of the FrameId. | 171 // ring buffer is the lower 8 bits of the FrameId. |
119 media::cast::RtpTimeTicks frame_rtp_timestamps_[256]; | 172 media::cast::RtpTimeTicks frame_rtp_timestamps_[256]; |
120 | 173 |
121 // This flag indicates whether CancelFramesInFlight() was called. | 174 // Queue of pending input operations. |input_queue_discards_remaining_| |
122 bool last_frame_was_canceled_; | 175 // indicates the number of operations where data should be discarded (due to |
| 176 // CancelInFlightData()). |
| 177 std::queue<base::Callback<bool(bool)>> input_queue_; |
| 178 size_t input_queue_discards_remaining_; |
| 179 |
| 180 // Watches |pipe_| for more data to become available, and then calls |
| 181 // ProcessInputQueue(). |
| 182 mojo::Watcher pipe_watcher_; |
| 183 |
| 184 // Set to true if the first frame has not yet been sent, or if a |
| 185 // CancelInFlightData() operation just completed. This causes TrySendFrame() |
| 186 // to mark the next frame as the start of a new sequence. |
| 187 bool flow_restart_pending_; |
123 | 188 |
124 // NOTE: Weak pointers must be invalidated before all other member variables. | 189 // NOTE: Weak pointers must be invalidated before all other member variables. |
125 base::WeakPtrFactory<CastRemotingSender> weak_factory_; | 190 base::WeakPtrFactory<CastRemotingSender> weak_factory_; |
126 | 191 |
127 DISALLOW_COPY_AND_ASSIGN(CastRemotingSender); | 192 DISALLOW_COPY_AND_ASSIGN(CastRemotingSender); |
128 }; | 193 }; |
129 | 194 |
130 } // namespace cast | 195 } // namespace cast |
131 | 196 |
132 #endif // CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ | 197 #endif // CHROME_BROWSER_MEDIA_CAST_REMOTING_SENDER_H_ |
OLD | NEW |