Chromium Code Reviews| 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 |