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/transport/cast_transport_sender_impl.h" 6 7 #include "base/single_thread_task_runner.h" 8 #include "media/cast/transport/cast_transport_config.h" 9 #include "media/cast/transport/cast_transport_defines.h" 10 #include "net/base/net_util.h" 11 12 namespace media { 13 namespace cast { 14 namespace transport { 15 16 scoped_ptr<CastTransportSender> CastTransportSender::Create( 17 net::NetLog* net_log, 18 base::TickClock* clock, 19 const net::IPEndPoint& remote_end_point, 20 const CastTransportStatusCallback& status_callback, 21 const BulkRawEventsCallback& raw_events_callback, 22 base::TimeDelta raw_events_callback_interval, 23 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) { 24 return scoped_ptr<CastTransportSender>( 25 new CastTransportSenderImpl(net_log, 26 clock, 27 remote_end_point, 28 status_callback, 29 raw_events_callback, 30 raw_events_callback_interval, 31 transport_task_runner.get(), 32 NULL)); 33 } 34 35 CastTransportSenderImpl::CastTransportSenderImpl( 36 net::NetLog* net_log, 37 base::TickClock* clock, 38 const net::IPEndPoint& remote_end_point, 39 const CastTransportStatusCallback& status_callback, 40 const BulkRawEventsCallback& raw_events_callback, 41 base::TimeDelta raw_events_callback_interval, 42 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner, 43 PacketSender* external_transport) 44 : clock_(clock), 45 status_callback_(status_callback), 46 transport_task_runner_(transport_task_runner), 47 transport_(external_transport ? NULL 48 : new UdpTransport(net_log, 49 transport_task_runner, 50 net::IPEndPoint(), 51 remote_end_point, 52 status_callback)), 53 logging_(), 54 pacer_(clock, 55 &logging_, 56 external_transport ? external_transport : transport_.get(), 57 transport_task_runner), 58 rtcp_builder_(&pacer_), 59 raw_events_callback_(raw_events_callback) { 60 DCHECK(clock_); 61 if (!raw_events_callback_.is_null()) { 62 DCHECK(raw_events_callback_interval > base::TimeDelta()); 63 event_subscriber_.reset(new SimpleEventSubscriber); 64 logging_.AddRawEventSubscriber(event_subscriber_.get()); 65 raw_events_timer_.Start(FROM_HERE, 66 raw_events_callback_interval, 67 this, 68 &CastTransportSenderImpl::SendRawEvents); 69 } 70 if (transport_) { 71 // The default DSCP value for cast is AF41. Which gives it a higher 72 // priority over other traffic. 73 transport_->SetDscp(net::DSCP_AF41); 74 } 75 } 76 77 CastTransportSenderImpl::~CastTransportSenderImpl() { 78 if (event_subscriber_.get()) 79 logging_.RemoveRawEventSubscriber(event_subscriber_.get()); 80 } 81 82 void CastTransportSenderImpl::InitializeAudio( 83 const CastTransportAudioConfig& config) { 84 LOG_IF(WARNING, config.rtp.config.aes_key.empty() || 85 config.rtp.config.aes_iv_mask.empty()) 86 << "Unsafe to send audio with encryption DISABLED."; 87 if (!audio_encryptor_.Initialize(config.rtp.config.aes_key, 88 config.rtp.config.aes_iv_mask)) { 89 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); 90 return; 91 } 92 audio_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); 93 if (audio_sender_->InitializeAudio(config)) { 94 pacer_.RegisterAudioSsrc(config.rtp.config.ssrc); 95 status_callback_.Run(TRANSPORT_AUDIO_INITIALIZED); 96 } else { 97 audio_sender_.reset(); 98 status_callback_.Run(TRANSPORT_AUDIO_UNINITIALIZED); 99 } 100 } 101 102 void CastTransportSenderImpl::InitializeVideo( 103 const CastTransportVideoConfig& config) { 104 LOG_IF(WARNING, config.rtp.config.aes_key.empty() || 105 config.rtp.config.aes_iv_mask.empty()) 106 << "Unsafe to send video with encryption DISABLED."; 107 if (!video_encryptor_.Initialize(config.rtp.config.aes_key, 108 config.rtp.config.aes_iv_mask)) { 109 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); 110 return; 111 } 112 video_sender_.reset(new RtpSender(clock_, transport_task_runner_, &pacer_)); 113 if (video_sender_->InitializeVideo(config)) { 114 pacer_.RegisterVideoSsrc(config.rtp.config.ssrc); 115 status_callback_.Run(TRANSPORT_VIDEO_INITIALIZED); 116 } else { 117 video_sender_.reset(); 118 status_callback_.Run(TRANSPORT_VIDEO_UNINITIALIZED); 119 } 120 } 121 122 void CastTransportSenderImpl::SetPacketReceiver( 123 const PacketReceiverCallback& packet_receiver) { 124 transport_->StartReceiving(packet_receiver); 125 } 126 127 namespace { 128 void EncryptAndSendFrame(const EncodedFrame& frame, 129 TransportEncryptionHandler* encryptor, 130 RtpSender* sender) { 131 if (encryptor->initialized()) { 132 EncodedFrame encrypted_frame; 133 frame.CopyMetadataTo(&encrypted_frame); 134 if (encryptor->Encrypt(frame.frame_id, frame.data, &encrypted_frame.data)) { 135 sender->SendFrame(encrypted_frame); 136 } else { 137 LOG(ERROR) << "Encryption failed. Not sending frame with ID " 138 << frame.frame_id; 139 } 140 } else { 141 sender->SendFrame(frame); 142 } 143 } 144 } // namespace 145 146 void CastTransportSenderImpl::InsertCodedAudioFrame( 147 const EncodedFrame& audio_frame) { 148 DCHECK(audio_sender_) << "Audio sender uninitialized"; 149 EncryptAndSendFrame(audio_frame, &audio_encryptor_, audio_sender_.get()); 150 } 151 152 void CastTransportSenderImpl::InsertCodedVideoFrame( 153 const EncodedFrame& video_frame) { 154 DCHECK(video_sender_) << "Video sender uninitialized"; 155 EncryptAndSendFrame(video_frame, &video_encryptor_, video_sender_.get()); 156 } 157 158 void CastTransportSenderImpl::SendRtcpFromRtpSender( 159 uint32 packet_type_flags, 160 uint32 ntp_seconds, 161 uint32 ntp_fraction, 162 uint32 rtp_timestamp, 163 const RtcpDlrrReportBlock& dlrr, 164 uint32 sending_ssrc, 165 const std::string& c_name) { 166 RtcpSenderInfo sender_info; 167 sender_info.ntp_seconds = ntp_seconds; 168 sender_info.ntp_fraction = ntp_fraction; 169 sender_info.rtp_timestamp = rtp_timestamp; 170 if (audio_sender_ && audio_sender_->ssrc() == sending_ssrc) { 171 sender_info.send_packet_count = audio_sender_->send_packet_count(); 172 sender_info.send_octet_count = audio_sender_->send_octet_count(); 173 } else if (video_sender_ && video_sender_->ssrc() == sending_ssrc) { 174 sender_info.send_packet_count = video_sender_->send_packet_count(); 175 sender_info.send_octet_count = video_sender_->send_octet_count(); 176 } else { 177 LOG(ERROR) << "Sending RTCP with an invalid SSRC."; 178 return; 179 } 180 rtcp_builder_.SendRtcpFromRtpSender( 181 packet_type_flags, sender_info, dlrr, sending_ssrc, c_name); 182 } 183 184 void CastTransportSenderImpl::ResendPackets( 185 bool is_audio, 186 const MissingFramesAndPacketsMap& missing_packets, 187 bool cancel_rtx_if_not_in_list, 188 base::TimeDelta dedupe_window) { 189 if (is_audio) { 190 DCHECK(audio_sender_) << "Audio sender uninitialized"; 191 audio_sender_->ResendPackets(missing_packets, 192 cancel_rtx_if_not_in_list, 193 dedupe_window); 194 } else { 195 DCHECK(video_sender_) << "Video sender uninitialized"; 196 video_sender_->ResendPackets(missing_packets, 197 cancel_rtx_if_not_in_list, 198 dedupe_window); 199 } 200 } 201 202 void CastTransportSenderImpl::SendRawEvents() { 203 DCHECK(event_subscriber_.get()); 204 DCHECK(!raw_events_callback_.is_null()); 205 std::vector<PacketEvent> packet_events; 206 event_subscriber_->GetPacketEventsAndReset(&packet_events); 207 raw_events_callback_.Run(packet_events); 208 } 209 210 } // namespace transport 211 } // namespace cast 212 } // namespace media 213