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.
5 #include "media/cast/net/cast_transport_sender_impl.h"
7 #include "base/single_thread_task_runner.h"
8 #include "base/values.h"
9 #include "media/cast/net/cast_transport_defines.h"
10 #include "media/cast/net/udp_transport.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/network_interfaces.h"
19 // See header file for what these mean.
20 const char kOptionDscp
[] = "DSCP";
22 const char kOptionNonBlockingIO
[] = "non_blocking_io";
24 const char kOptionPacerTargetBurstSize
[] = "pacer_target_burst_size";
25 const char kOptionPacerMaxBurstSize
[] = "pacer_max_burst_size";
26 const char kOptionSendBufferMinSize
[] = "send_buffer_min_size";
27 const char kOptionWifiDisableScan
[] = "disable_wifi_scan";
28 const char kOptionWifiMediaStreamingMode
[] = "media_streaming_mode";
30 int LookupOptionWithDefault(const base::DictionaryValue
& options
,
31 const std::string
& path
,
34 if (options
.GetInteger(path
, &ret
)) {
41 int32
GetTransportSendBufferSize(const base::DictionaryValue
& options
) {
42 // Socket send buffer size needs to be at least greater than one burst
44 int32 max_burst_size
=
45 LookupOptionWithDefault(options
, kOptionPacerMaxBurstSize
,
46 kMaxBurstSize
) * kMaxIpPacketSize
;
47 int32 min_send_buffer_size
=
48 LookupOptionWithDefault(options
, kOptionSendBufferMinSize
, 0);
49 return std::max(max_burst_size
, min_send_buffer_size
);
54 scoped_ptr
<CastTransportSender
> CastTransportSender::Create(
56 base::TickClock
* clock
,
57 const net::IPEndPoint
& local_end_point
,
58 const net::IPEndPoint
& remote_end_point
,
59 scoped_ptr
<base::DictionaryValue
> options
,
60 const CastTransportStatusCallback
& status_callback
,
61 const BulkRawEventsCallback
& raw_events_callback
,
62 base::TimeDelta raw_events_callback_interval
,
63 const PacketReceiverCallback
& packet_callback
,
64 const scoped_refptr
<base::SingleThreadTaskRunner
>& transport_task_runner
) {
65 return scoped_ptr
<CastTransportSender
>(
66 new CastTransportSenderImpl(net_log
,
73 raw_events_callback_interval
,
74 transport_task_runner
.get(),
79 PacketReceiverCallback
CastTransportSender::PacketReceiverForTesting() {
80 return PacketReceiverCallback();
83 CastTransportSenderImpl::CastTransportSenderImpl(
85 base::TickClock
* clock
,
86 const net::IPEndPoint
& local_end_point
,
87 const net::IPEndPoint
& remote_end_point
,
88 scoped_ptr
<base::DictionaryValue
> options
,
89 const CastTransportStatusCallback
& status_callback
,
90 const BulkRawEventsCallback
& raw_events_callback
,
91 base::TimeDelta raw_events_callback_interval
,
92 const scoped_refptr
<base::SingleThreadTaskRunner
>& transport_task_runner
,
93 const PacketReceiverCallback
& packet_callback
,
94 PacketSender
* external_transport
)
96 status_callback_(status_callback
),
97 transport_task_runner_(transport_task_runner
),
101 new UdpTransport(net_log
,
102 transport_task_runner
,
105 GetTransportSendBufferSize(*options
),
107 pacer_(LookupOptionWithDefault(*options
,
108 kOptionPacerTargetBurstSize
,
110 LookupOptionWithDefault(*options
,
111 kOptionPacerMaxBurstSize
,
115 external_transport
? external_transport
: transport_
.get(),
116 transport_task_runner
),
117 raw_events_callback_(raw_events_callback
),
118 raw_events_callback_interval_(raw_events_callback_interval
),
119 last_byte_acked_for_audio_(0),
120 packet_callback_(packet_callback
),
121 weak_factory_(this) {
123 if (!raw_events_callback_
.is_null()) {
124 DCHECK(raw_events_callback_interval
> base::TimeDelta());
125 event_subscriber_
.reset(new SimpleEventSubscriber
);
126 logging_
.AddRawEventSubscriber(event_subscriber_
.get());
127 transport_task_runner
->PostDelayedTask(
129 base::Bind(&CastTransportSenderImpl::SendRawEvents
,
130 weak_factory_
.GetWeakPtr()),
131 raw_events_callback_interval
);
134 if (options
->HasKey(kOptionDscp
)) {
135 // The default DSCP value for cast is AF41. Which gives it a higher
136 // priority over other traffic.
137 transport_
->SetDscp(net::DSCP_AF41
);
140 if (options
->HasKey(kOptionNonBlockingIO
)) {
141 transport_
->UseNonBlockingIO();
144 transport_
->StartReceiving(
145 base::Bind(&CastTransportSenderImpl::OnReceivedPacket
,
146 base::Unretained(this)));
147 int wifi_options
= 0;
148 if (options
->HasKey(kOptionWifiDisableScan
)) {
149 wifi_options
|= net::WIFI_OPTIONS_DISABLE_SCAN
;
151 if (options
->HasKey(kOptionWifiMediaStreamingMode
)) {
152 wifi_options
|= net::WIFI_OPTIONS_MEDIA_STREAMING_MODE
;
155 wifi_options_autoreset_
= net::SetWifiOptions(wifi_options
);
160 CastTransportSenderImpl::~CastTransportSenderImpl() {
162 transport_
->StopReceiving();
164 if (event_subscriber_
.get())
165 logging_
.RemoveRawEventSubscriber(event_subscriber_
.get());
168 void CastTransportSenderImpl::InitializeAudio(
169 const CastTransportRtpConfig
& config
,
170 const RtcpCastMessageCallback
& cast_message_cb
,
171 const RtcpRttCallback
& rtt_cb
) {
172 LOG_IF(WARNING
, config
.aes_key
.empty() || config
.aes_iv_mask
.empty())
173 << "Unsafe to send audio with encryption DISABLED.";
174 if (!audio_encryptor_
.Initialize(config
.aes_key
, config
.aes_iv_mask
)) {
175 status_callback_
.Run(TRANSPORT_AUDIO_UNINITIALIZED
);
179 audio_sender_
.reset(new RtpSender(transport_task_runner_
, &pacer_
));
180 if (audio_sender_
->Initialize(config
)) {
181 // Audio packets have a higher priority.
182 pacer_
.RegisterAudioSsrc(config
.ssrc
);
183 pacer_
.RegisterPrioritySsrc(config
.ssrc
);
184 status_callback_
.Run(TRANSPORT_AUDIO_INITIALIZED
);
186 audio_sender_
.reset();
187 status_callback_
.Run(TRANSPORT_AUDIO_UNINITIALIZED
);
191 audio_rtcp_session_
.reset(
192 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage
,
193 weak_factory_
.GetWeakPtr(), config
.ssrc
,
196 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage
,
197 weak_factory_
.GetWeakPtr(), AUDIO_EVENT
),
201 config
.feedback_ssrc
));
202 pacer_
.RegisterAudioSsrc(config
.ssrc
);
203 AddValidSsrc(config
.feedback_ssrc
);
204 status_callback_
.Run(TRANSPORT_AUDIO_INITIALIZED
);
207 void CastTransportSenderImpl::InitializeVideo(
208 const CastTransportRtpConfig
& config
,
209 const RtcpCastMessageCallback
& cast_message_cb
,
210 const RtcpRttCallback
& rtt_cb
) {
211 LOG_IF(WARNING
, config
.aes_key
.empty() || config
.aes_iv_mask
.empty())
212 << "Unsafe to send video with encryption DISABLED.";
213 if (!video_encryptor_
.Initialize(config
.aes_key
, config
.aes_iv_mask
)) {
214 status_callback_
.Run(TRANSPORT_VIDEO_UNINITIALIZED
);
218 video_sender_
.reset(new RtpSender(transport_task_runner_
, &pacer_
));
219 if (!video_sender_
->Initialize(config
)) {
220 video_sender_
.reset();
221 status_callback_
.Run(TRANSPORT_VIDEO_UNINITIALIZED
);
225 video_rtcp_session_
.reset(
226 new Rtcp(base::Bind(&CastTransportSenderImpl::OnReceivedCastMessage
,
227 weak_factory_
.GetWeakPtr(), config
.ssrc
,
230 base::Bind(&CastTransportSenderImpl::OnReceivedLogMessage
,
231 weak_factory_
.GetWeakPtr(), VIDEO_EVENT
),
235 config
.feedback_ssrc
));
236 pacer_
.RegisterVideoSsrc(config
.ssrc
);
237 AddValidSsrc(config
.feedback_ssrc
);
238 status_callback_
.Run(TRANSPORT_VIDEO_INITIALIZED
);
242 void EncryptAndSendFrame(const EncodedFrame
& frame
,
243 TransportEncryptionHandler
* encryptor
,
245 if (encryptor
->is_activated()) {
246 EncodedFrame encrypted_frame
;
247 frame
.CopyMetadataTo(&encrypted_frame
);
248 if (encryptor
->Encrypt(frame
.frame_id
, frame
.data
, &encrypted_frame
.data
)) {
249 sender
->SendFrame(encrypted_frame
);
251 LOG(ERROR
) << "Encryption failed. Not sending frame with ID "
255 sender
->SendFrame(frame
);
260 void CastTransportSenderImpl::InsertFrame(uint32 ssrc
,
261 const EncodedFrame
& frame
) {
262 if (audio_sender_
&& ssrc
== audio_sender_
->ssrc()) {
263 EncryptAndSendFrame(frame
, &audio_encryptor_
, audio_sender_
.get());
264 } else if (video_sender_
&& ssrc
== video_sender_
->ssrc()) {
265 EncryptAndSendFrame(frame
, &video_encryptor_
, video_sender_
.get());
267 NOTREACHED() << "Invalid InsertFrame call.";
271 void CastTransportSenderImpl::SendSenderReport(
273 base::TimeTicks current_time
,
274 uint32 current_time_as_rtp_timestamp
) {
275 if (audio_sender_
&& ssrc
== audio_sender_
->ssrc()) {
276 audio_rtcp_session_
->SendRtcpFromRtpSender(
277 current_time
, current_time_as_rtp_timestamp
,
278 audio_sender_
->send_packet_count(), audio_sender_
->send_octet_count());
279 } else if (video_sender_
&& ssrc
== video_sender_
->ssrc()) {
280 video_rtcp_session_
->SendRtcpFromRtpSender(
281 current_time
, current_time_as_rtp_timestamp
,
282 video_sender_
->send_packet_count(), video_sender_
->send_octet_count());
284 NOTREACHED() << "Invalid request for sending RTCP packet.";
288 void CastTransportSenderImpl::CancelSendingFrames(
290 const std::vector
<uint32
>& frame_ids
) {
291 if (audio_sender_
&& ssrc
== audio_sender_
->ssrc()) {
292 audio_sender_
->CancelSendingFrames(frame_ids
);
293 } else if (video_sender_
&& ssrc
== video_sender_
->ssrc()) {
294 video_sender_
->CancelSendingFrames(frame_ids
);
296 NOTREACHED() << "Invalid request for cancel sending.";
300 void CastTransportSenderImpl::ResendFrameForKickstart(uint32 ssrc
,
302 if (audio_sender_
&& ssrc
== audio_sender_
->ssrc()) {
303 DCHECK(audio_rtcp_session_
);
304 audio_sender_
->ResendFrameForKickstart(
306 audio_rtcp_session_
->current_round_trip_time());
307 } else if (video_sender_
&& ssrc
== video_sender_
->ssrc()) {
308 DCHECK(video_rtcp_session_
);
309 video_sender_
->ResendFrameForKickstart(
311 video_rtcp_session_
->current_round_trip_time());
313 NOTREACHED() << "Invalid request for kickstart.";
317 void CastTransportSenderImpl::ResendPackets(
319 const MissingFramesAndPacketsMap
& missing_packets
,
320 bool cancel_rtx_if_not_in_list
,
321 const DedupInfo
& dedup_info
) {
322 if (audio_sender_
&& ssrc
== audio_sender_
->ssrc()) {
323 audio_sender_
->ResendPackets(missing_packets
,
324 cancel_rtx_if_not_in_list
,
326 } else if (video_sender_
&& ssrc
== video_sender_
->ssrc()) {
327 video_sender_
->ResendPackets(missing_packets
,
328 cancel_rtx_if_not_in_list
,
331 NOTREACHED() << "Invalid request for retransmission.";
335 PacketReceiverCallback
CastTransportSenderImpl::PacketReceiverForTesting() {
337 base::IgnoreResult(&CastTransportSenderImpl::OnReceivedPacket
),
338 weak_factory_
.GetWeakPtr());
341 void CastTransportSenderImpl::SendRawEvents() {
342 DCHECK(event_subscriber_
.get());
343 DCHECK(!raw_events_callback_
.is_null());
344 std::vector
<PacketEvent
> packet_events
;
345 std::vector
<FrameEvent
> frame_events
;
346 event_subscriber_
->GetPacketEventsAndReset(&packet_events
);
347 event_subscriber_
->GetFrameEventsAndReset(&frame_events
);
348 raw_events_callback_
.Run(packet_events
, frame_events
);
350 transport_task_runner_
->PostDelayedTask(
352 base::Bind(&CastTransportSenderImpl::SendRawEvents
,
353 weak_factory_
.GetWeakPtr()),
354 raw_events_callback_interval_
);
357 bool CastTransportSenderImpl::OnReceivedPacket(scoped_ptr
<Packet
> packet
) {
358 const uint8_t* const data
= &packet
->front();
359 const size_t length
= packet
->size();
361 if (Rtcp::IsRtcpPacket(data
, length
)) {
362 ssrc
= Rtcp::GetSsrcOfSender(data
, length
);
363 } else if (!RtpParser::ParseSsrc(data
, length
, &ssrc
)) {
364 VLOG(1) << "Invalid RTP packet.";
367 if (valid_ssrcs_
.find(ssrc
) == valid_ssrcs_
.end()) {
368 VLOG(1) << "Stale packet received.";
372 if (audio_rtcp_session_
&&
373 audio_rtcp_session_
->IncomingRtcpPacket(data
, length
)) {
376 if (video_rtcp_session_
&&
377 video_rtcp_session_
->IncomingRtcpPacket(data
, length
)) {
380 if (packet_callback_
.is_null()) {
381 VLOG(1) << "Stale packet received.";
384 packet_callback_
.Run(packet
.Pass());
388 void CastTransportSenderImpl::OnReceivedLogMessage(
389 EventMediaType media_type
,
390 const RtcpReceiverLogMessage
& log
) {
391 // Add received log messages into our log system.
392 RtcpReceiverLogMessage::const_iterator it
= log
.begin();
393 for (; it
!= log
.end(); ++it
) {
394 uint32 rtp_timestamp
= it
->rtp_timestamp_
;
396 RtcpReceiverEventLogMessages::const_iterator event_it
=
397 it
->event_log_messages_
.begin();
398 for (; event_it
!= it
->event_log_messages_
.end(); ++event_it
) {
399 switch (event_it
->type
) {
400 case PACKET_RECEIVED
:
401 logging_
.InsertPacketEvent(
402 event_it
->event_timestamp
, event_it
->type
,
403 media_type
, rtp_timestamp
,
404 kFrameIdUnknown
, event_it
->packet_id
, 0, 0);
408 logging_
.InsertFrameEvent(
409 event_it
->event_timestamp
, event_it
->type
, media_type
,
410 rtp_timestamp
, kFrameIdUnknown
);
413 logging_
.InsertFrameEventWithDelay(
414 event_it
->event_timestamp
, event_it
->type
, media_type
,
415 rtp_timestamp
, kFrameIdUnknown
, event_it
->delay_delta
);
418 VLOG(2) << "Received log message via RTCP that we did not expect: "
419 << static_cast<int>(event_it
->type
);
426 void CastTransportSenderImpl::OnReceivedCastMessage(
428 const RtcpCastMessageCallback
& cast_message_cb
,
429 const RtcpCastMessage
& cast_message
) {
430 if (!cast_message_cb
.is_null())
431 cast_message_cb
.Run(cast_message
);
433 DedupInfo dedup_info
;
434 if (audio_sender_
&& audio_sender_
->ssrc() == ssrc
) {
435 const int64 acked_bytes
=
436 audio_sender_
->GetLastByteSentForFrame(cast_message
.ack_frame_id
);
437 last_byte_acked_for_audio_
=
438 std::max(acked_bytes
, last_byte_acked_for_audio_
);
439 } else if (video_sender_
&& video_sender_
->ssrc() == ssrc
) {
440 dedup_info
.resend_interval
= video_rtcp_session_
->current_round_trip_time();
442 // Only use audio stream to dedup if there is one.
444 dedup_info
.last_byte_acked_for_audio
= last_byte_acked_for_audio_
;
448 if (cast_message
.missing_frames_and_packets
.empty())
451 // This call does two things.
452 // 1. Specifies that retransmissions for packets not listed in the set are
454 // 2. Specifies a deduplication window. For video this would be the most
455 // recent RTT. For audio there is no deduplication.
457 cast_message
.missing_frames_and_packets
,
462 void CastTransportSenderImpl::AddValidSsrc(uint32 ssrc
) {
463 valid_ssrcs_
.insert(ssrc
);
466 void CastTransportSenderImpl::SendRtcpFromRtpReceiver(
469 const RtcpTimeData
& time_data
,
470 const RtcpCastMessage
* cast_message
,
471 base::TimeDelta target_delay
,
472 const ReceiverRtcpEventSubscriber::RtcpEvents
* rtcp_events
,
473 const RtpReceiverStatistics
* rtp_receiver_statistics
) {
474 const Rtcp
rtcp(RtcpCastMessageCallback(),
476 RtcpLogMessageCallback(),
481 rtcp
.SendRtcpFromRtpReceiver(time_data
,
485 rtp_receiver_statistics
);