• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
LookupOptionWithDefault(const base::DictionaryValue & options,const std::string & path,int default_value)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 
Create(net::NetLog * net_log,base::TickClock * clock,const net::IPEndPoint & remote_end_point,scoped_ptr<base::DictionaryValue> options,const CastTransportStatusCallback & status_callback,const BulkRawEventsCallback & raw_events_callback,base::TimeDelta raw_events_callback_interval,const scoped_refptr<base::SingleThreadTaskRunner> & transport_task_runner)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 
PacketReceiverForTesting()52 PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() {
53   return PacketReceiverCallback();
54 }
55 
CastTransportSenderImpl(net::NetLog * net_log,base::TickClock * clock,const net::IPEndPoint & remote_end_point,scoped_ptr<base::DictionaryValue> options,const CastTransportStatusCallback & status_callback,const BulkRawEventsCallback & raw_events_callback,base::TimeDelta raw_events_callback_interval,const scoped_refptr<base::SingleThreadTaskRunner> & transport_task_runner,PacketSender * external_transport)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 
~CastTransportSenderImpl()122 CastTransportSenderImpl::~CastTransportSenderImpl() {
123   if (event_subscriber_.get())
124     logging_.RemoveRawEventSubscriber(event_subscriber_.get());
125 }
126 
InitializeAudio(const CastTransportRtpConfig & config,const RtcpCastMessageCallback & cast_message_cb,const RtcpRttCallback & rtt_cb)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 
InitializeVideo(const CastTransportRtpConfig & config,const RtcpCastMessageCallback & cast_message_cb,const RtcpRttCallback & rtt_cb)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 {
EncryptAndSendFrame(const EncodedFrame & frame,TransportEncryptionHandler * encryptor,RtpSender * sender)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 
InsertFrame(uint32 ssrc,const EncodedFrame & frame)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 
SendSenderReport(uint32 ssrc,base::TimeTicks current_time,uint32 current_time_as_rtp_timestamp)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 
CancelSendingFrames(uint32 ssrc,const std::vector<uint32> & frame_ids)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 
ResendFrameForKickstart(uint32 ssrc,uint32 frame_id)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 
ResendPackets(uint32 ssrc,const MissingFramesAndPacketsMap & missing_packets,bool cancel_rtx_if_not_in_list,const DedupInfo & dedup_info)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 
PacketReceiverForTesting()292 PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() {
293   return base::Bind(&CastTransportSenderImpl::OnReceivedPacket,
294                     weak_factory_.GetWeakPtr());
295 }
296 
SendRawEvents()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 
OnReceivedPacket(scoped_ptr<Packet> packet)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 
OnReceivedLogMessage(EventMediaType media_type,const RtcpReceiverLogMessage & log)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 
OnReceivedCastMessage(uint32 ssrc,const RtcpCastMessageCallback & cast_message_cb,const RtcpCastMessage & cast_message)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