Home | History | Annotate | Download | only in media
      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 "chrome/browser/media/cast_transport_host_filter.h"
      6 
      7 #include "chrome/browser/browser_process.h"
      8 #include "chrome/browser/net/chrome_net_log.h"
      9 #include "content/public/browser/power_save_blocker.h"
     10 #include "media/cast/net/cast_transport_sender.h"
     11 
     12 namespace {
     13 
     14 // How often to send raw events.
     15 const int kSendRawEventsIntervalSecs = 1;
     16 
     17 }
     18 
     19 namespace cast {
     20 
     21 CastTransportHostFilter::CastTransportHostFilter()
     22     : BrowserMessageFilter(CastMsgStart),
     23       weak_factory_(this) {}
     24 
     25 CastTransportHostFilter::~CastTransportHostFilter() {}
     26 
     27 bool CastTransportHostFilter::OnMessageReceived(const IPC::Message& message) {
     28   bool handled = true;
     29   IPC_BEGIN_MESSAGE_MAP(CastTransportHostFilter, message)
     30     IPC_MESSAGE_HANDLER(CastHostMsg_New, OnNew)
     31     IPC_MESSAGE_HANDLER(CastHostMsg_Delete, OnDelete)
     32     IPC_MESSAGE_HANDLER(CastHostMsg_InitializeAudio, OnInitializeAudio)
     33     IPC_MESSAGE_HANDLER(CastHostMsg_InitializeVideo, OnInitializeVideo)
     34     IPC_MESSAGE_HANDLER(CastHostMsg_InsertFrame, OnInsertFrame)
     35     IPC_MESSAGE_HANDLER(CastHostMsg_SendSenderReport,
     36                         OnSendSenderReport)
     37     IPC_MESSAGE_HANDLER(CastHostMsg_ResendFrameForKickstart,
     38                         OnResendFrameForKickstart)
     39     IPC_MESSAGE_HANDLER(CastHostMsg_CancelSendingFrames,
     40                         OnCancelSendingFrames)
     41     IPC_MESSAGE_UNHANDLED(handled = false);
     42   IPC_END_MESSAGE_MAP();
     43   return handled;
     44 }
     45 
     46 void CastTransportHostFilter::NotifyStatusChange(
     47     int32 channel_id,
     48     media::cast::CastTransportStatus status) {
     49   Send(new CastMsg_NotifyStatusChange(channel_id, status));
     50 }
     51 
     52 void CastTransportHostFilter::SendRawEvents(
     53     int32 channel_id,
     54     const std::vector<media::cast::PacketEvent>& packet_events,
     55     const std::vector<media::cast::FrameEvent>& frame_events) {
     56   if (!packet_events.empty())
     57     Send(new CastMsg_RawEvents(channel_id,
     58                                packet_events,
     59                                frame_events));
     60 }
     61 
     62 void CastTransportHostFilter::SendRtt(int32 channel_id,
     63                                       uint32 ssrc,
     64                                       base::TimeDelta rtt) {
     65   Send(new CastMsg_Rtt(channel_id, ssrc, rtt));
     66 }
     67 
     68 void CastTransportHostFilter::SendCastMessage(
     69     int32 channel_id,
     70     uint32 ssrc,
     71     const media::cast::RtcpCastMessage& cast_message) {
     72   Send(new CastMsg_RtcpCastMessage(channel_id, ssrc, cast_message));
     73 }
     74 
     75 void CastTransportHostFilter::OnNew(
     76     int32 channel_id,
     77     const net::IPEndPoint& remote_end_point,
     78     const base::DictionaryValue& options) {
     79   if (!power_save_blocker_) {
     80     DVLOG(1) << ("Preventing the application from being suspended while one or "
     81                  "more transports are active for Cast Streaming.");
     82     power_save_blocker_ = content::PowerSaveBlocker::Create(
     83         content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
     84         "Cast is streaming content to a remote receiver.").Pass();
     85   }
     86 
     87   if (id_map_.Lookup(channel_id)) {
     88     id_map_.Remove(channel_id);
     89   }
     90 
     91   scoped_ptr<media::cast::CastTransportSender> sender =
     92       media::cast::CastTransportSender::Create(
     93           g_browser_process->net_log(),
     94           &clock_,
     95           remote_end_point,
     96           make_scoped_ptr(options.DeepCopy()),
     97           base::Bind(&CastTransportHostFilter::NotifyStatusChange,
     98                      weak_factory_.GetWeakPtr(),
     99                      channel_id),
    100           base::Bind(&CastTransportHostFilter::SendRawEvents,
    101                      weak_factory_.GetWeakPtr(),
    102                      channel_id),
    103           base::TimeDelta::FromSeconds(kSendRawEventsIntervalSecs),
    104           base::MessageLoopProxy::current());
    105   id_map_.AddWithID(sender.release(), channel_id);
    106 }
    107 
    108 void CastTransportHostFilter::OnDelete(int32 channel_id) {
    109   media::cast::CastTransportSender* sender =
    110       id_map_.Lookup(channel_id);
    111   if (sender) {
    112     id_map_.Remove(channel_id);
    113   } else {
    114     DVLOG(1) << "CastTransportHostFilter::Delete called "
    115              << "on non-existing channel";
    116   }
    117 
    118   if (id_map_.IsEmpty()) {
    119     DVLOG_IF(1, power_save_blocker_) <<
    120         ("Releasing the block on application suspension since no transports "
    121          "are active anymore for Cast Streaming.");
    122     power_save_blocker_.reset();
    123   }
    124 }
    125 
    126 void CastTransportHostFilter::OnInitializeAudio(
    127     int32 channel_id,
    128     const media::cast::CastTransportRtpConfig& config) {
    129   media::cast::CastTransportSender* sender =
    130       id_map_.Lookup(channel_id);
    131   if (sender) {
    132     sender->InitializeAudio(
    133         config,
    134         base::Bind(&CastTransportHostFilter::SendCastMessage,
    135                    weak_factory_.GetWeakPtr(),
    136                    channel_id, config.ssrc),
    137         base::Bind(&CastTransportHostFilter::SendRtt,
    138                    weak_factory_.GetWeakPtr(),
    139                    channel_id, config.ssrc));
    140   } else {
    141     DVLOG(1)
    142         << "CastTransportHostFilter::OnInitializeAudio on non-existing channel";
    143   }
    144 }
    145 
    146 void CastTransportHostFilter::OnInitializeVideo(
    147     int32 channel_id,
    148     const media::cast::CastTransportRtpConfig& config) {
    149   media::cast::CastTransportSender* sender =
    150       id_map_.Lookup(channel_id);
    151   if (sender) {
    152     sender->InitializeVideo(
    153         config,
    154         base::Bind(&CastTransportHostFilter::SendCastMessage,
    155                    weak_factory_.GetWeakPtr(),
    156                    channel_id, config.ssrc),
    157         base::Bind(&CastTransportHostFilter::SendRtt,
    158                    weak_factory_.GetWeakPtr(),
    159                    channel_id, config.ssrc));
    160   } else {
    161     DVLOG(1)
    162         << "CastTransportHostFilter::OnInitializeVideo on non-existing channel";
    163   }
    164 }
    165 
    166 void CastTransportHostFilter::OnInsertFrame(
    167     int32 channel_id,
    168     uint32 ssrc,
    169     const media::cast::EncodedFrame& frame) {
    170   media::cast::CastTransportSender* sender =
    171       id_map_.Lookup(channel_id);
    172   if (sender) {
    173     sender->InsertFrame(ssrc, frame);
    174   } else {
    175     DVLOG(1)
    176         << "CastTransportHostFilter::OnInsertFrame on non-existing channel";
    177   }
    178 }
    179 
    180 void CastTransportHostFilter::OnCancelSendingFrames(
    181     int32 channel_id, uint32 ssrc,
    182     const std::vector<uint32>& frame_ids) {
    183   media::cast::CastTransportSender* sender =
    184       id_map_.Lookup(channel_id);
    185   if (sender) {
    186     sender->CancelSendingFrames(ssrc, frame_ids);
    187   } else {
    188     DVLOG(1)
    189         << "CastTransportHostFilter::OnCancelSendingFrames "
    190         << "on non-existing channel";
    191   }
    192 }
    193 
    194 void CastTransportHostFilter::OnResendFrameForKickstart(
    195     int32 channel_id, uint32 ssrc, uint32 frame_id) {
    196   media::cast::CastTransportSender* sender =
    197       id_map_.Lookup(channel_id);
    198   if (sender) {
    199     sender->ResendFrameForKickstart(ssrc, frame_id);
    200   } else {
    201     DVLOG(1)
    202         << "CastTransportHostFilter::OnResendFrameForKickstart "
    203         << "on non-existing channel";
    204   }
    205 }
    206 
    207 void CastTransportHostFilter::OnSendSenderReport(
    208     int32 channel_id,
    209     uint32 ssrc,
    210     base::TimeTicks current_time,
    211     uint32 current_time_as_rtp_timestamp) {
    212   media::cast::CastTransportSender* sender =
    213       id_map_.Lookup(channel_id);
    214   if (sender) {
    215     sender->SendSenderReport(ssrc,
    216                              current_time,
    217                              current_time_as_rtp_timestamp);
    218   } else {
    219     DVLOG(1)
    220         << "CastTransportHostFilter::OnSendSenderReport "
    221         << "on non-existing channel";
    222   }
    223 }
    224 
    225 }  // namespace cast
    226