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 "chrome/browser/media/cast_transport_host_filter.h"
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"
14 // How often to send raw events.
15 const int kSendRawEventsIntervalSecs = 1;
21 CastTransportHostFilter::CastTransportHostFilter()
22 : BrowserMessageFilter(CastMsgStart),
23 weak_factory_(this) {}
25 CastTransportHostFilter::~CastTransportHostFilter() {}
27 bool CastTransportHostFilter::OnMessageReceived(const IPC::Message& message) {
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_InsertCodedAudioFrame,
35 OnInsertCodedAudioFrame)
36 IPC_MESSAGE_HANDLER(CastHostMsg_InsertCodedVideoFrame,
37 OnInsertCodedVideoFrame)
38 IPC_MESSAGE_HANDLER(CastHostMsg_SendSenderReport,
40 IPC_MESSAGE_HANDLER(CastHostMsg_ResendPackets,
42 IPC_MESSAGE_UNHANDLED(handled = false);
43 IPC_END_MESSAGE_MAP();
47 void CastTransportHostFilter::NotifyStatusChange(
49 media::cast::CastTransportStatus status) {
50 Send(new CastMsg_NotifyStatusChange(channel_id, status));
53 void CastTransportHostFilter::SendRawEvents(
55 const std::vector<media::cast::PacketEvent>& packet_events,
56 const std::vector<media::cast::FrameEvent>& frame_events) {
57 if (!packet_events.empty())
58 Send(new CastMsg_RawEvents(channel_id,
63 void CastTransportHostFilter::SendRtt(int32 channel_id,
66 base::TimeDelta avg_rtt,
67 base::TimeDelta min_rtt,
68 base::TimeDelta max_rtt) {
69 media::cast::RtcpRttReport report;
71 report.avg_rtt = avg_rtt;
72 report.min_rtt = min_rtt;
73 report.max_rtt = max_rtt;
74 Send(new CastMsg_Rtt(channel_id, ssrc, report));
77 void CastTransportHostFilter::SendCastMessage(
80 const media::cast::RtcpCastMessage& cast_message) {
81 Send(new CastMsg_RtcpCastMessage(channel_id, ssrc, cast_message));
84 void CastTransportHostFilter::OnNew(
86 const net::IPEndPoint& remote_end_point) {
87 if (!power_save_blocker_) {
88 DVLOG(1) << ("Preventing the application from being suspended while one or "
89 "more transports are active for Cast Streaming.");
90 power_save_blocker_ = content::PowerSaveBlocker::Create(
91 content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
92 "Cast is streaming content to a remote receiver.").Pass();
95 if (id_map_.Lookup(channel_id)) {
96 id_map_.Remove(channel_id);
99 scoped_ptr<media::cast::CastTransportSender> sender =
100 media::cast::CastTransportSender::Create(
101 g_browser_process->net_log(),
104 base::Bind(&CastTransportHostFilter::NotifyStatusChange,
105 weak_factory_.GetWeakPtr(),
107 base::Bind(&CastTransportHostFilter::SendRawEvents,
108 weak_factory_.GetWeakPtr(),
110 base::TimeDelta::FromSeconds(kSendRawEventsIntervalSecs),
111 base::MessageLoopProxy::current());
112 id_map_.AddWithID(sender.release(), channel_id);
115 void CastTransportHostFilter::OnDelete(int32 channel_id) {
116 media::cast::CastTransportSender* sender =
117 id_map_.Lookup(channel_id);
119 id_map_.Remove(channel_id);
121 DVLOG(1) << "CastTransportHostFilter::Delete called "
122 << "on non-existing channel";
125 if (id_map_.IsEmpty()) {
126 DVLOG_IF(1, power_save_blocker_) <<
127 ("Releasing the block on application suspension since no transports "
128 "are active anymore for Cast Streaming.");
129 power_save_blocker_.reset();
133 void CastTransportHostFilter::OnInitializeAudio(
135 const media::cast::CastTransportRtpConfig& config) {
136 media::cast::CastTransportSender* sender =
137 id_map_.Lookup(channel_id);
139 sender->InitializeAudio(
141 base::Bind(&CastTransportHostFilter::SendCastMessage,
142 weak_factory_.GetWeakPtr(),
143 channel_id, config.ssrc),
144 base::Bind(&CastTransportHostFilter::SendRtt,
145 weak_factory_.GetWeakPtr(),
146 channel_id, config.ssrc));
149 << "CastTransportHostFilter::OnInitializeAudio on non-existing channel";
153 void CastTransportHostFilter::OnInitializeVideo(
155 const media::cast::CastTransportRtpConfig& config) {
156 media::cast::CastTransportSender* sender =
157 id_map_.Lookup(channel_id);
159 sender->InitializeVideo(
161 base::Bind(&CastTransportHostFilter::SendCastMessage,
162 weak_factory_.GetWeakPtr(),
163 channel_id, config.ssrc),
164 base::Bind(&CastTransportHostFilter::SendRtt,
165 weak_factory_.GetWeakPtr(),
166 channel_id, config.ssrc));
169 << "CastTransportHostFilter::OnInitializeVideo on non-existing channel";
173 void CastTransportHostFilter::OnInsertCodedAudioFrame(
175 const media::cast::EncodedFrame& audio_frame) {
176 media::cast::CastTransportSender* sender =
177 id_map_.Lookup(channel_id);
179 sender->InsertCodedAudioFrame(audio_frame);
182 << "CastTransportHostFilter::OnInsertCodedAudioFrame "
183 << "on non-existing channel";
187 void CastTransportHostFilter::OnInsertCodedVideoFrame(
189 const media::cast::EncodedFrame& video_frame) {
190 media::cast::CastTransportSender* sender =
191 id_map_.Lookup(channel_id);
193 sender->InsertCodedVideoFrame(video_frame);
196 << "CastTransportHostFilter::OnInsertCodedVideoFrame "
197 << "on non-existing channel";
201 void CastTransportHostFilter::OnSendSenderReport(
204 base::TimeTicks current_time,
205 uint32 current_time_as_rtp_timestamp) {
206 media::cast::CastTransportSender* sender =
207 id_map_.Lookup(channel_id);
209 sender->SendSenderReport(ssrc,
211 current_time_as_rtp_timestamp);
214 << "CastTransportHostFilter::OnSendSenderReport "
215 << "on non-existing channel";
219 void CastTransportHostFilter::OnResendPackets(
222 const media::cast::MissingFramesAndPacketsMap& missing_packets,
223 bool cancel_rtx_if_not_in_list,
224 base::TimeDelta dedupe_window) {
225 media::cast::CastTransportSender* sender =
226 id_map_.Lookup(channel_id);
228 sender->ResendPackets(
229 is_audio, missing_packets, cancel_rtx_if_not_in_list, dedupe_window);
232 << "CastTransportHostFilter::OnResendPackets on non-existing channel";