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/transport/cast_transport_sender_impl.h"
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"
16 scoped_ptr
<CastTransportSender
> CastTransportSender::Create(
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
,
30 raw_events_callback_interval
,
31 transport_task_runner
.get(),
35 CastTransportSenderImpl::CastTransportSenderImpl(
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
)
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
,
56 external_transport
? external_transport
: transport_
.get(),
57 transport_task_runner
),
58 rtcp_builder_(&pacer_
),
59 raw_events_callback_(raw_events_callback
) {
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
,
68 &CastTransportSenderImpl::SendRawEvents
);
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
);
77 CastTransportSenderImpl::~CastTransportSenderImpl() {
78 if (event_subscriber_
.get())
79 logging_
.RemoveRawEventSubscriber(event_subscriber_
.get());
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
);
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
);
97 audio_sender_
.reset();
98 status_callback_
.Run(TRANSPORT_AUDIO_UNINITIALIZED
);
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
);
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
);
117 video_sender_
.reset();
118 status_callback_
.Run(TRANSPORT_VIDEO_UNINITIALIZED
);
122 void CastTransportSenderImpl::SetPacketReceiver(
123 const PacketReceiverCallback
& packet_receiver
) {
124 transport_
->StartReceiving(packet_receiver
);
128 void EncryptAndSendFrame(const EncodedFrame
& frame
,
129 TransportEncryptionHandler
* encryptor
,
131 if (encryptor
->is_activated()) {
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
);
137 LOG(ERROR
) << "Encryption failed. Not sending frame with ID "
141 sender
->SendFrame(frame
);
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());
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());
158 void CastTransportSenderImpl::SendRtcpFromRtpSender(
159 uint32 packet_type_flags
,
162 uint32 rtp_timestamp
,
163 const RtcpDlrrReportBlock
& dlrr
,
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();
177 LOG(ERROR
) << "Sending RTCP with an invalid SSRC.";
180 rtcp_builder_
.SendRtcpFromRtpSender(
181 packet_type_flags
, sender_info
, dlrr
, sending_ssrc
, c_name
);
184 void CastTransportSenderImpl::ResendPackets(
186 const MissingFramesAndPacketsMap
& missing_packets
,
187 bool cancel_rtx_if_not_in_list
,
188 base::TimeDelta dedupe_window
) {
190 DCHECK(audio_sender_
) << "Audio sender uninitialized";
191 audio_sender_
->ResendPackets(missing_packets
,
192 cancel_rtx_if_not_in_list
,
195 DCHECK(video_sender_
) << "Video sender uninitialized";
196 video_sender_
->ResendPackets(missing_packets
,
197 cancel_rtx_if_not_in_list
,
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
);
210 } // namespace transport