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 3 // found in the LICENSE file. 4 5 #include "media/cast/net/cast_transport_sender_impl.h" 6 7 #include "base/single_thread_task_runner.h" 8 #include "base/values.h" 9 #include "media/cast/net/cast_transport_config.h" 10 #include "media/cast/net/cast_transport_defines.h" 11 #include "media/cast/net/udp_transport.h" 12 #include "net/base/net_util.h" 13 14 namespace media { 15 namespace cast { 16 17 namespace { 18 int LookupOptionWithDefault(const base::DictionaryValue& options, 19 const std::string& path, 20 int default_value) { 21 int ret; 22 if (options.GetInteger(path, &ret)) { 23 return ret; 24 } else { 25 return default_value; 26 } 27 }; 28 29 } // namespace 30 31 scoped_ptr<CastTransportSender> CastTransportSender::Create( 32 net::NetLog* net_log, 33 base::TickClock* clock, 34 const net::IPEndPoint& remote_end_point, 35 scoped_ptr<base::DictionaryValue> options, 36 const CastTransportStatusCallback& status_callback, 37 const BulkRawEventsCallback& raw_events_callback, 38 base::TimeDelta raw_events_callback_interval, 39 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) { 40 return scoped_ptr<CastTransportSender>( 41 new CastTransportSenderImpl(net_log, 42 clock, 43 remote_end_point, 44 options.Pass(), 45 status_callback, 46 raw_events_callback, 47 raw_events_callback_interval, 48 transport_task_runner.get(), 49 NULL)); 50 } 51 52 PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() { 53 return PacketReceiverCallback(); 54 } 55 56 CastTransportSenderImpl::CastTransportSenderImpl( 57 net::NetLog* net_log, 58 base::TickClock* clock, 59 const net::IPEndPoint& remote_end_point, 60 scoped_ptr<base::DictionaryValue> options, 61 const CastTransportStatusCallback& status_callback, 62 const BulkRawEventsCallback& raw_events_callback, 63 base::TimeDelta raw_events_callback_interval, 64 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, 65 PacketSender* external_transport) 66 : clock_(clock), 67 status_callback_(status_callback), 68 transport_task_runner_(transport_task_runner), 69 transport_(external_transport ? NULL 70 : new UdpTransport(net_log, 71 transport_task_runner, 72 net::IPEndPoint(), 73 remote_end_point, 74 status_callback)), 75 pacer_(LookupOptionWithDefault(*options.get(), 76 "pacer_target_burst_size", 77 kTargetBurstSize), 78 LookupOptionWithDefault(*options.get(), 79 "pacer_max_burst_size", 80 kMaxBurstSize), 81 clock, 82 &logging_, 83 external_transport ? external_transport : transport_.get(), 84 transport_task_runner), 85 raw_events_callback_(raw_events_callback), 86 raw_events_callback_interval_(raw_events_callback_interval), 87 last_byte_acked_for_audio_(0), 88 weak_factory_(this) { 89 DCHECK(clock_); 90 if (!raw_events_callback_.is_null()) { 91 DCHECK(raw_events_callback_interval > base::TimeDelta()); 92 event_subscriber_.reset(new SimpleEventSubscriber); 93 logging_.AddRawEventSubscriber(event_subscriber_.get()); 94 transport_task_runner->PostDelayedTask( 95 FROM_HERE, 96 base::Bind(&CastTransportSenderImpl::SendRawEvents, 97 weak_factory_.GetWeakPtr()), 98 raw_events_callback_interval); 99 } 100 if (transport_) { 101 if (options->HasKey("DSCP")) { 102 // The default DSCP value for cast is AF41. Which gives it a higher 103 // priority over other traffic. 104 transport_->SetDscp(net::DSCP_AF41); 105 } 106 transport_->StartReceiving( 107 base::Bind(&CastTransportSenderImpl::OnReceivedPacket, 108 weak_factory_.GetWeakPtr())); 109 int wifi_options = 0; 110 if (options->HasKey("disable_wifi_scan")) { 111 wifi_options |= net::WIFI_OPTIONS_DISABLE_SCAN; 112 } 113 if (options->HasKey("media_streaming_mode")) { 114 wifi_options |= net::WIFI_OPTIONS_MEDIA_STREAMING_MODE; 115 } 116 if (wifi_options) { 117 wifi_options_autoreset_ = net::SetWifiOptions(wifi_options); 118 } 119 } 120 } 121 122 CastTransportSenderImpl::~CastTransportSenderImpl() { 123 if (event_subscriber_.get()) 124 logging_.RemoveRawEventSubscriber(event_subscriber_.get()); 125 } 126 127 void CastTransportSenderImpl::InitializeAudio( 128 const CastTransportRtpConfig& config, 129 const RtcpCastMessageCallback& cast_message_cb, 130 const RtcpRttCallback& rtt_cb) { 131 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty()) 132 << "Unsafe to send audio with encryption DISABLED."; 133 if (!audio_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) { 134 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); 135 return; 136 } 137 138 audio_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); 139 if (audio_sender_->Initialize(config)) { 140 // Audio packets have a higher priority. 141 pacer_.RegisterAudioSsrc(config.ssrc); 142 pacer_.RegisterPrioritySsrc(config.ssrc); 143 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); 144 } else { 145 audio_sender_.reset(); 146 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); 147 return; 148 } 149 150 audio_rtcp_session_.reset( 151 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage, 152 weak_factory_.GetWeakPtr(), config.ssrc, 153 cast_message_cb), 154 rtt_cb, 155 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, 156 weak_factory_.GetWeakPtr(), AUDIO_EVENT), 157 clock_, 158 &pacer_, 159 config.ssrc, 160 config.feedback_ssrc)); 161 pacer_.RegisterAudioSsrc(config.ssrc); 162 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); 163 } 164 165 void CastTransportSenderImpl::InitializeVideo( 166 const CastTransportRtpConfig& config, 167 const RtcpCastMessageCallback& cast_message_cb, 168 const RtcpRttCallback& rtt_cb) { 169 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty()) 170 << "Unsafe to send video with encryption DISABLED."; 171 if (!video_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) { 172 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); 173 return; 174 } 175 176 video_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); 177 if (!video_sender_->Initialize(config)) { 178 video_sender_.reset(); 179 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); 180 return; 181 } 182 183 video_rtcp_session_.reset( 184 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage, 185 weak_factory_.GetWeakPtr(), config.ssrc, 186 cast_message_cb), 187 rtt_cb, 188 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage, 189 weak_factory_.GetWeakPtr(), VIDEO_EVENT), 190 clock_, 191 &pacer_, 192 config.ssrc, 193 config.feedback_ssrc)); 194 pacer_.RegisterVideoSsrc(config.ssrc); 195 status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); 196 } 197 198 namespace { 199 void EncryptAndSendFrame(const EncodedFrame& frame, 200 TransportEncryptionHandler* encryptor, 201 RtpSender* sender) { 202 if (encryptor->is_activated()) { 203 EncodedFrame encrypted_frame; 204 frame.CopyMetadataTo(&encrypted_frame); 205 if (encryptor->Encrypt(frame.frame_id, frame.data, &encrypted_frame.data)) { 206 sender->SendFrame(encrypted_frame); 207 } else { 208 LOG(ERROR) << "Encryption failed. Not sending frame with ID " 209 << frame.frame_id; 210 } 211 } else { 212 sender->SendFrame(frame); 213 } 214 } 215 } // namespace 216 217 void CastTransportSenderImpl::InsertFrame(uint32 ssrc, 218 const EncodedFrame& frame) { 219 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 220 EncryptAndSendFrame(frame, &audio_encryptor_, audio_sender_.get()); 221 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { 222 EncryptAndSendFrame(frame, &video_encryptor_, video_sender_.get()); 223 } else { 224 NOTREACHED() << "Invalid InsertFrame call."; 225 } 226 } 227 228 void CastTransportSenderImpl::SendSenderReport( 229 uint32 ssrc, 230 base::TimeTicks current_time, 231 uint32 current_time_as_rtp_timestamp) { 232 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 233 audio_rtcp_session_->SendRtcpFromRtpSender( 234 current_time, current_time_as_rtp_timestamp, 235 audio_sender_->send_packet_count(), audio_sender_->send_octet_count()); 236 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { 237 video_rtcp_session_->SendRtcpFromRtpSender( 238 current_time, current_time_as_rtp_timestamp, 239 video_sender_->send_packet_count(), video_sender_->send_octet_count()); 240 } else { 241 NOTREACHED() << "Invalid request for sending RTCP packet."; 242 } 243 } 244 245 void CastTransportSenderImpl::CancelSendingFrames( 246 uint32 ssrc, 247 const std::vector<uint32>& frame_ids) { 248 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 249 audio_sender_->CancelSendingFrames(frame_ids); 250 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { 251 video_sender_->CancelSendingFrames(frame_ids); 252 } else { 253 NOTREACHED() << "Invalid request for cancel sending."; 254 } 255 } 256 257 void CastTransportSenderImpl::ResendFrameForKickstart(uint32 ssrc, 258 uint32 frame_id) { 259 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 260 DCHECK(audio_rtcp_session_); 261 audio_sender_->ResendFrameForKickstart( 262 frame_id, 263 audio_rtcp_session_->current_round_trip_time()); 264 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { 265 DCHECK(video_rtcp_session_); 266 video_sender_->ResendFrameForKickstart( 267 frame_id, 268 video_rtcp_session_->current_round_trip_time()); 269 } else { 270 NOTREACHED() << "Invalid request for kickstart."; 271 } 272 } 273 274 void CastTransportSenderImpl::ResendPackets( 275 uint32 ssrc, 276 const MissingFramesAndPacketsMap& missing_packets, 277 bool cancel_rtx_if_not_in_list, 278 const DedupInfo& dedup_info) { 279 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 280 audio_sender_->ResendPackets(missing_packets, 281 cancel_rtx_if_not_in_list, 282 dedup_info); 283 } else if (video_sender_ && ssrc == video_sender_->ssrc()) { 284 video_sender_->ResendPackets(missing_packets, 285 cancel_rtx_if_not_in_list, 286 dedup_info); 287 } else { 288 NOTREACHED() << "Invalid request for retransmission."; 289 } 290 } 291 292 PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() { 293 return base::Bind(&CastTransportSenderImpl::OnReceivedPacket, 294 weak_factory_.GetWeakPtr()); 295 } 296 297 void CastTransportSenderImpl::SendRawEvents() { 298 DCHECK(event_subscriber_.get()); 299 DCHECK(!raw_events_callback_.is_null()); 300 std::vector<PacketEvent> packet_events; 301 std::vector<FrameEvent> frame_events; 302 event_subscriber_->GetPacketEventsAndReset(&packet_events); 303 event_subscriber_->GetFrameEventsAndReset(&frame_events); 304 raw_events_callback_.Run(packet_events, frame_events); 305 306 transport_task_runner_->PostDelayedTask( 307 FROM_HERE, 308 base::Bind(&CastTransportSenderImpl::SendRawEvents, 309 weak_factory_.GetWeakPtr()), 310 raw_events_callback_interval_); 311 } 312 313 void CastTransportSenderImpl::OnReceivedPacket(scoped_ptr<Packet> packet) { 314 if (audio_rtcp_session_ && 315 audio_rtcp_session_->IncomingRtcpPacket(&packet->front(), 316 packet->size())) { 317 return; 318 } 319 if (video_rtcp_session_ && 320 video_rtcp_session_->IncomingRtcpPacket(&packet->front(), 321 packet->size())) { 322 return; 323 } 324 VLOG(1) << "Stale packet received."; 325 } 326 327 void CastTransportSenderImpl::OnReceivedLogMessage( 328 EventMediaType media_type, 329 const RtcpReceiverLogMessage& log) { 330 // Add received log messages into our log system. 331 RtcpReceiverLogMessage::const_iterator it = log.begin(); 332 for (; it != log.end(); ++it) { 333 uint32 rtp_timestamp = it->rtp_timestamp_; 334 335 RtcpReceiverEventLogMessages::const_iterator event_it = 336 it->event_log_messages_.begin(); 337 for (; event_it != it->event_log_messages_.end(); ++event_it) { 338 switch (event_it->type) { 339 case PACKET_RECEIVED: 340 logging_.InsertPacketEvent( 341 event_it->event_timestamp, event_it->type, 342 media_type, rtp_timestamp, 343 kFrameIdUnknown, event_it->packet_id, 0, 0); 344 break; 345 case FRAME_ACK_SENT: 346 case FRAME_DECODED: 347 logging_.InsertFrameEvent( 348 event_it->event_timestamp, event_it->type, media_type, 349 rtp_timestamp, kFrameIdUnknown); 350 break; 351 case FRAME_PLAYOUT: 352 logging_.InsertFrameEventWithDelay( 353 event_it->event_timestamp, event_it->type, media_type, 354 rtp_timestamp, kFrameIdUnknown, event_it->delay_delta); 355 break; 356 default: 357 VLOG(2) << "Received log message via RTCP that we did not expect: " 358 << static_cast<int>(event_it->type); 359 break; 360 } 361 } 362 } 363 } 364 365 void CastTransportSenderImpl::OnReceivedCastMessage( 366 uint32 ssrc, 367 const RtcpCastMessageCallback& cast_message_cb, 368 const RtcpCastMessage& cast_message) { 369 if (!cast_message_cb.is_null()) 370 cast_message_cb.Run(cast_message); 371 372 DedupInfo dedup_info; 373 if (audio_sender_ && audio_sender_->ssrc() == ssrc) { 374 const int64 acked_bytes = 375 audio_sender_->GetLastByteSentForFrame(cast_message.ack_frame_id); 376 last_byte_acked_for_audio_ = 377 std::max(acked_bytes, last_byte_acked_for_audio_); 378 } else if (video_sender_ && video_sender_->ssrc() == ssrc) { 379 dedup_info.resend_interval = video_rtcp_session_->current_round_trip_time(); 380 381 // Only use audio stream to dedup if there is one. 382 if (audio_sender_) { 383 dedup_info.last_byte_acked_for_audio = last_byte_acked_for_audio_; 384 } 385 } 386 387 if (cast_message.missing_frames_and_packets.empty()) 388 return; 389 390 // This call does two things. 391 // 1. Specifies that retransmissions for packets not listed in the set are 392 // cancelled. 393 // 2. Specifies a deduplication window. For video this would be the most 394 // recent RTT. For audio there is no deduplication. 395 ResendPackets(ssrc, 396 cast_message.missing_frames_and_packets, 397 true, 398 dedup_info); 399 } 400 401 } // namespace cast 402 } // namespace media 403