Home | History | Annotate | Download | only in transport
      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