Home | History | Annotate | Download | only in net
      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 {
     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 
     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 
     52 PacketReceiverCallback CastTransportSender::PacketReceiverForTesting() {
     53   return PacketReceiverCallback();
     54 }
     55 
     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 
    122 CastTransportSenderImpl::~CastTransportSenderImpl() {
    123   if (event_subscriber_.get())
    124     logging_.RemoveRawEventSubscriber(event_subscriber_.get());
    125 }
    126 
    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 
    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 {
    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 
    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 
    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 
    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 
    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 
    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 
    292 PacketReceiverCallback CastTransportSenderImpl::PacketReceiverForTesting() {
    293   return base::Bind(&CastTransportSenderImpl::OnReceivedPacket,
    294                     weak_factory_.GetWeakPtr());
    295 }
    296 
    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 
    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 
    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 
    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