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