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 12namespace { 13 14// How often to send raw events. 15const int kSendRawEventsIntervalSecs = 1; 16 17} 18 19namespace cast { 20 21CastTransportHostFilter::CastTransportHostFilter() 22 : BrowserMessageFilter(CastMsgStart), 23 weak_factory_(this) {} 24 25CastTransportHostFilter::~CastTransportHostFilter() {} 26 27bool 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 46void CastTransportHostFilter::NotifyStatusChange( 47 int32 channel_id, 48 media::cast::CastTransportStatus status) { 49 Send(new CastMsg_NotifyStatusChange(channel_id, status)); 50} 51 52void 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 62void CastTransportHostFilter::SendRtt(int32 channel_id, 63 uint32 ssrc, 64 base::TimeDelta rtt) { 65 Send(new CastMsg_Rtt(channel_id, ssrc, rtt)); 66} 67 68void 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 75void 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 108void 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 126void 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 146void 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 166void 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 180void 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 194void 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 207void 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