OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "media/cast/net/cast_transport_sender_impl.h" | 5 #include "media/cast/net/cast_transport_sender_impl.h" |
6 | 6 |
7 #include "base/single_thread_task_runner.h" | 7 #include "base/single_thread_task_runner.h" |
8 #include "media/cast/net/cast_transport_config.h" | 8 #include "media/cast/net/cast_transport_config.h" |
9 #include "media/cast/net/cast_transport_defines.h" | 9 #include "media/cast/net/cast_transport_defines.h" |
10 #include "media/cast/net/udp_transport.h" | 10 #include "media/cast/net/udp_transport.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 pacer_.RegisterAudioSsrc(config.ssrc); | 104 pacer_.RegisterAudioSsrc(config.ssrc); |
105 pacer_.RegisterPrioritySsrc(config.ssrc); | 105 pacer_.RegisterPrioritySsrc(config.ssrc); |
106 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); | 106 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); |
107 } else { | 107 } else { |
108 audio_sender_.reset(); | 108 audio_sender_.reset(); |
109 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); | 109 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); |
110 return; | 110 return; |
111 } | 111 } |
112 | 112 |
113 audio_rtcp_session_.reset( | 113 audio_rtcp_session_.reset( |
114 new Rtcp(cast_message_cb, | 114 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage, |
115 rtt_cb, | 115 weak_factory_.GetWeakPtr(), config.ssrc, |
116 cast_message_cb), | |
117 base::Bind(&CastTransportSenderImpl::OnReceivedRtt, | |
118 weak_factory_.GetWeakPtr(), rtt_cb), | |
116 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, | 119 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, |
117 weak_factory_.GetWeakPtr(), AUDIO_EVENT), | 120 weak_factory_.GetWeakPtr(), AUDIO_EVENT), |
118 clock_, | 121 clock_, |
119 &pacer_, | 122 &pacer_, |
120 config.ssrc, | 123 config.ssrc, |
121 config.feedback_ssrc)); | 124 config.feedback_ssrc)); |
122 pacer_.RegisterAudioSsrc(config.ssrc); | 125 pacer_.RegisterAudioSsrc(config.ssrc); |
123 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); | 126 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); |
124 } | 127 } |
125 | 128 |
126 void CastTransportSenderImpl::InitializeVideo( | 129 void CastTransportSenderImpl::InitializeVideo( |
127 const CastTransportRtpConfig& config, | 130 const CastTransportRtpConfig& config, |
128 const RtcpCastMessageCallback& cast_message_cb, | 131 const RtcpCastMessageCallback& cast_message_cb, |
129 const RtcpRttCallback& rtt_cb) { | 132 const RtcpRttCallback& rtt_cb) { |
130 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty()) | 133 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty()) |
131 << "Unsafe to send video with encryption DISABLED."; | 134 << "Unsafe to send video with encryption DISABLED."; |
132 if (!video_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) { | 135 if (!video_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) { |
133 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); | 136 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); |
134 return; | 137 return; |
135 } | 138 } |
136 | 139 |
137 video_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); | 140 video_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); |
138 if (!video_sender_->Initialize(config)) { | 141 if (!video_sender_->Initialize(config)) { |
139 video_sender_.reset(); | 142 video_sender_.reset(); |
140 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); | 143 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); |
141 return; | 144 return; |
142 } | 145 } |
143 | 146 |
144 video_rtcp_session_.reset( | 147 video_rtcp_session_.reset( |
145 new Rtcp(cast_message_cb, | 148 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage, |
hubbe
2014/08/11 19:11:49
Do we really want one rtcp object for audio and on
Alpha Left Google
2014/08/11 21:03:17
Yes we do. RTCP object maintain some states intern
| |
146 rtt_cb, | 149 weak_factory_.GetWeakPtr(), config.ssrc, |
150 cast_message_cb), | |
151 base::Bind(&CastTransportSenderImpl::OnReceivedRtt, | |
152 weak_factory_.GetWeakPtr(), rtt_cb), | |
147 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, | 153 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, |
148 weak_factory_.GetWeakPtr(), VIDEO_EVENT), | 154 weak_factory_.GetWeakPtr(), VIDEO_EVENT), |
149 clock_, | 155 clock_, |
150 &pacer_, | 156 &pacer_, |
151 config.ssrc, | 157 config.ssrc, |
152 config.feedback_ssrc)); | 158 config.feedback_ssrc)); |
153 pacer_.RegisterVideoSsrc(config.ssrc); | 159 pacer_.RegisterVideoSsrc(config.ssrc); |
154 status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); | 160 status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); |
155 } | 161 } |
156 | 162 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 audio_sender_->send_packet_count(), audio_sender_->send_octet_count()); | 201 audio_sender_->send_packet_count(), audio_sender_->send_octet_count()); |
196 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { | 202 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { |
197 video_rtcp_session_->SendRtcpFromRtpSender( | 203 video_rtcp_session_->SendRtcpFromRtpSender( |
198 current_time, current_time_as_rtp_timestamp, | 204 current_time, current_time_as_rtp_timestamp, |
199 video_sender_->send_packet_count(), video_sender_->send_octet_count()); | 205 video_sender_->send_packet_count(), video_sender_->send_octet_count()); |
200 } else { | 206 } else { |
201 NOTREACHED() << "Invalid request for sending RTCP packet."; | 207 NOTREACHED() << "Invalid request for sending RTCP packet."; |
202 } | 208 } |
203 } | 209 } |
204 | 210 |
211 void CastTransportSenderImpl::CancelSendingFrames( | |
212 uint32 ssrc, | |
213 const std::set<uint32>& frame_ids) { | |
214 // Cancel resends of acked frames. | |
215 MissingFramesAndPacketsMap missing_frames_and_packets; | |
216 PacketIdSet missing; | |
217 for (std::set<uint32>::const_iterator it = frame_ids.begin(); | |
218 it != frame_ids.end(); ++it) { | |
219 missing_frames_and_packets[*it] = missing; | |
220 } | |
221 ResendPackets(ssrc, missing_frames_and_packets, true, base::TimeDelta()); | |
hubbe
2014/08/11 19:11:50
Why not call audio/video_sender->CancelSendingFram
Alpha Left Google
2014/08/11 21:03:18
Done.
| |
222 } | |
223 | |
224 void CastTransportSenderImpl::ResendFrameForKickstart(uint32 ssrc, | |
225 uint32 frame_id) { | |
226 // Send the last packet of the encoded frame to kick start | |
227 // retransmission. This gives enough information to the receiver what | |
228 // packets and frames are missing. | |
229 MissingFramesAndPacketsMap missing_frames_and_packets; | |
230 PacketIdSet missing; | |
231 missing.insert(kRtcpCastLastPacket); | |
232 missing_frames_and_packets.insert(std::make_pair(frame_id, missing)); | |
233 | |
234 // Sending this extra packet is to kick-start the session. There is | |
235 // no need to optimize re-transmission for this case. | |
236 ResendPackets(ssrc, missing_frames_and_packets, false, most_recent_rtt_); | |
hubbe
2014/08/11 19:11:49
Why not call audio/video_sender_->ResendFrameForKi
Alpha Left Google
2014/08/11 21:03:17
Done.
| |
237 } | |
238 | |
205 void CastTransportSenderImpl::ResendPackets( | 239 void CastTransportSenderImpl::ResendPackets( |
206 bool is_audio, | 240 uint32 ssrc, |
207 const MissingFramesAndPacketsMap& missing_packets, | 241 const MissingFramesAndPacketsMap& missing_packets, |
208 bool cancel_rtx_if_not_in_list, | 242 bool cancel_rtx_if_not_in_list, |
209 base::TimeDelta dedupe_window) { | 243 base::TimeDelta dedupe_window) { |
210 if (is_audio) { | 244 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { |
211 DCHECK(audio_sender_) << "Audio sender uninitialized"; | |
212 audio_sender_->ResendPackets(missing_packets, | 245 audio_sender_->ResendPackets(missing_packets, |
213 cancel_rtx_if_not_in_list, | 246 cancel_rtx_if_not_in_list, |
214 dedupe_window); | 247 dedupe_window); |
215 } else { | 248 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { |
216 DCHECK(video_sender_) << "Video sender uninitialized"; | |
217 video_sender_->ResendPackets(missing_packets, | 249 video_sender_->ResendPackets(missing_packets, |
218 cancel_rtx_if_not_in_list, | 250 cancel_rtx_if_not_in_list, |
219 dedupe_window); | 251 dedupe_window); |
252 } else { | |
253 NOTREACHED() << "Invalid request for retransmission."; | |
220 } | 254 } |
221 } | 255 } |
222 | 256 |
223 PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() { | 257 PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() { |
224 return base::Bind(&CastTransportSenderImpl::OnReceivedPacket, | 258 return base::Bind(&CastTransportSenderImpl::OnReceivedPacket, |
225 weak_factory_.GetWeakPtr()); | 259 weak_factory_.GetWeakPtr()); |
226 } | 260 } |
227 | 261 |
228 void CastTransportSenderImpl::SendRawEvents() { | 262 void CastTransportSenderImpl::SendRawEvents() { |
229 DCHECK(event_subscriber_.get()); | 263 DCHECK(event_subscriber_.get()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 break; | 320 break; |
287 default: | 321 default: |
288 VLOG(2) << "Received log message via RTCP that we did not expect: " | 322 VLOG(2) << "Received log message via RTCP that we did not expect: " |
289 << static_cast<int>(event_it->type); | 323 << static_cast<int>(event_it->type); |
290 break; | 324 break; |
291 } | 325 } |
292 } | 326 } |
293 } | 327 } |
294 } | 328 } |
295 | 329 |
330 void CastTransportSenderImpl::OnReceivedRtt(const RtcpRttCallback& rtt_cb, | |
331 base::TimeDelta rtt, | |
332 base::TimeDelta avg_rtt, | |
333 base::TimeDelta min_rtt, | |
334 base::TimeDelta max_rtt) { | |
335 if (!rtt_cb.is_null()) | |
336 rtt_cb.Run(rtt, avg_rtt, min_rtt, max_rtt); | |
337 | |
338 most_recent_rtt_ = rtt; | |
hubbe
2014/08/11 19:11:49
Seems like it would be cleaner to just have the rt
Alpha Left Google
2014/08/11 21:03:18
Done.
| |
339 } | |
340 | |
341 void CastTransportSenderImpl::OnReceivedCastMessage( | |
342 uint32 ssrc, | |
343 const RtcpCastMessageCallback& cast_message_cb, | |
344 const RtcpCastMessage& cast_message) { | |
345 if (!cast_message_cb.is_null()) | |
346 cast_message_cb.Run(cast_message); | |
347 | |
348 if (cast_message.missing_frames_and_packets.empty()) | |
349 return; | |
350 | |
351 const bool is_audio = audio_sender_ && audio_sender_->ssrc() == ssrc; | |
352 | |
353 // This call does two things. | |
354 // 1. Specifies that retransmissions for packets not listed in the set are | |
355 // cancelled. | |
356 // 2. Specifies a deduplication window. For video this would be the most | |
357 // recent RTT. For audio there is no deduplication. | |
358 ResendPackets(ssrc, | |
359 cast_message.missing_frames_and_packets, | |
360 true, | |
361 is_audio ? base::TimeDelta() : most_recent_rtt_); | |
362 } | |
363 | |
296 } // namespace cast | 364 } // namespace cast |
297 } // namespace media | 365 } // namespace media |
OLD | NEW |