OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/renderer_webmediaplayer_delegate.h" | 5 #include "content/renderer/media/renderer_webmediaplayer_delegate.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
11 #include "base/metrics/user_metrics_action.h" | 11 #include "base/metrics/user_metrics_action.h" |
12 #include "base/sys_info.h" | |
12 #include "content/common/media/media_player_delegate_messages.h" | 13 #include "content/common/media/media_player_delegate_messages.h" |
13 #include "content/public/renderer/render_frame.h" | 14 #include "content/public/renderer/render_frame.h" |
14 #include "content/public/renderer/render_thread.h" | 15 #include "content/public/renderer/render_thread.h" |
15 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" | 16 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" |
16 | 17 |
18 #if defined(OS_ANDROID) | |
19 #include "base/android/build_info.h" | |
20 #endif | |
21 | |
17 namespace { | 22 namespace { |
18 | 23 |
19 void RecordAction(const base::UserMetricsAction& action) { | 24 void RecordAction(const base::UserMetricsAction& action) { |
20 content::RenderThread::Get()->RecordAction(action); | 25 content::RenderThread::Get()->RecordAction(action); |
21 } | 26 } |
22 | 27 |
28 bool IsLowEndDevice() { | |
sandersd (OOO until July 31)
2016/09/13 23:02:42
Please comment that this check is specifically to
DaleCurtis
2016/09/15 23:03:55
Done.
| |
29 #if defined(OS_ANDROID) | |
30 return base::android::BuildInfo::GetInstance()->sdk_int() <= 18 || | |
31 base::SysInfo::IsLowEndDevice(); | |
32 #else | |
33 return base::SysInfo::IsLowEndDevice(); | |
34 #endif | |
35 } | |
36 | |
23 } // namespace | 37 } // namespace |
24 | 38 |
25 namespace media { | 39 namespace media { |
26 | 40 |
27 RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate( | 41 RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate( |
28 content::RenderFrame* render_frame) | 42 content::RenderFrame* render_frame) |
29 : RenderFrameObserver(render_frame), | 43 : RenderFrameObserver(render_frame), |
44 idle_cleanup_timer_(true, true), | |
30 default_tick_clock_(new base::DefaultTickClock()), | 45 default_tick_clock_(new base::DefaultTickClock()), |
31 tick_clock_(default_tick_clock_.get()) { | 46 tick_clock_(default_tick_clock_.get()) { |
32 idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5); | 47 idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5); |
33 idle_timeout_ = base::TimeDelta::FromSeconds(15); | 48 idle_timeout_ = base::TimeDelta::FromSeconds(15); |
34 } | 49 } |
35 | 50 |
36 RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {} | 51 RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {} |
37 | 52 |
38 int RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) { | 53 int RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) { |
39 const int delegate_id = id_map_.Add(observer); | 54 const int delegate_id = id_map_.Add(observer); |
(...skipping 16 matching lines...) Expand all Loading... | |
56 bool has_audio, | 71 bool has_audio, |
57 bool is_remote, | 72 bool is_remote, |
58 MediaContentType media_content_type) { | 73 MediaContentType media_content_type) { |
59 DCHECK(id_map_.Lookup(delegate_id)); | 74 DCHECK(id_map_.Lookup(delegate_id)); |
60 has_played_media_ = true; | 75 has_played_media_ = true; |
61 if (has_video && !is_remote) | 76 if (has_video && !is_remote) |
62 playing_videos_.insert(delegate_id); | 77 playing_videos_.insert(delegate_id); |
63 else | 78 else |
64 playing_videos_.erase(delegate_id); | 79 playing_videos_.erase(delegate_id); |
65 RemoveIdleDelegate(delegate_id); | 80 RemoveIdleDelegate(delegate_id); |
81 | |
82 // Upon receipt of a playback request, suspend everything that's not used. | |
83 if (IsLowEndDevice()) | |
84 CleanupIdleDelegates(base::TimeDelta()); | |
85 | |
66 Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying( | 86 Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying( |
67 routing_id(), delegate_id, has_video, has_audio, is_remote, | 87 routing_id(), delegate_id, has_video, has_audio, is_remote, |
68 media_content_type)); | 88 media_content_type)); |
69 } | 89 } |
70 | 90 |
71 void RendererWebMediaPlayerDelegate::DidPause(int delegate_id, | 91 void RendererWebMediaPlayerDelegate::DidPause(int delegate_id, |
72 bool reached_end_of_stream) { | 92 bool reached_end_of_stream) { |
73 DCHECK(id_map_.Lookup(delegate_id)); | 93 DCHECK(id_map_.Lookup(delegate_id)); |
74 AddIdleDelegate(delegate_id); | 94 AddIdleDelegate(delegate_id); |
75 if (reached_end_of_stream) | 95 if (reached_end_of_stream) |
76 playing_videos_.erase(delegate_id); | 96 playing_videos_.erase(delegate_id); |
77 Send(new MediaPlayerDelegateHostMsg_OnMediaPaused(routing_id(), delegate_id, | 97 Send(new MediaPlayerDelegateHostMsg_OnMediaPaused(routing_id(), delegate_id, |
78 reached_end_of_stream)); | 98 reached_end_of_stream)); |
79 } | 99 } |
80 | 100 |
81 void RendererWebMediaPlayerDelegate::PlayerGone(int delegate_id) { | 101 void RendererWebMediaPlayerDelegate::PlayerGone(int delegate_id) { |
82 DCHECK(id_map_.Lookup(delegate_id)); | 102 DCHECK(id_map_.Lookup(delegate_id)); |
83 RemoveIdleDelegate(delegate_id); | |
84 playing_videos_.erase(delegate_id); | 103 playing_videos_.erase(delegate_id); |
85 Send(new MediaPlayerDelegateHostMsg_OnMediaDestroyed(routing_id(), | 104 Send(new MediaPlayerDelegateHostMsg_OnMediaDestroyed(routing_id(), |
86 delegate_id)); | 105 delegate_id)); |
87 } | 106 } |
88 | 107 |
89 bool RendererWebMediaPlayerDelegate::IsHidden() { | 108 bool RendererWebMediaPlayerDelegate::IsHidden() { |
90 return render_frame()->IsHidden(); | 109 return render_frame()->IsHidden(); |
91 } | 110 } |
92 | 111 |
93 bool RendererWebMediaPlayerDelegate::IsPlayingBackgroundVideo() { | 112 bool RendererWebMediaPlayerDelegate::IsPlayingBackgroundVideo() { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 double multiplier) { | 183 double multiplier) { |
165 Observer* observer = id_map_.Lookup(delegate_id); | 184 Observer* observer = id_map_.Lookup(delegate_id); |
166 if (observer) | 185 if (observer) |
167 observer->OnVolumeMultiplierUpdate(multiplier); | 186 observer->OnVolumeMultiplierUpdate(multiplier); |
168 } | 187 } |
169 | 188 |
170 void RendererWebMediaPlayerDelegate::AddIdleDelegate(int delegate_id) { | 189 void RendererWebMediaPlayerDelegate::AddIdleDelegate(int delegate_id) { |
171 idle_delegate_map_[delegate_id] = tick_clock_->NowTicks(); | 190 idle_delegate_map_[delegate_id] = tick_clock_->NowTicks(); |
172 if (!idle_cleanup_timer_.IsRunning()) { | 191 if (!idle_cleanup_timer_.IsRunning()) { |
173 idle_cleanup_timer_.Start( | 192 idle_cleanup_timer_.Start( |
174 FROM_HERE, idle_cleanup_interval_, this, | 193 FROM_HERE, idle_cleanup_interval_, |
175 &RendererWebMediaPlayerDelegate::CleanupIdleDelegates); | 194 base::Bind(&RendererWebMediaPlayerDelegate::CleanupIdleDelegates, |
195 base::Unretained(this), idle_timeout_)); | |
176 } | 196 } |
197 | |
198 // When we reach the maximum number of idle players, aggressively suspend idle | |
199 // delegates to try and remain under the limit. | |
200 static const size_t kMaxIdlePlayers = IsLowEndDevice() ? 2 : 8; | |
201 if (idle_delegate_map_.size() > kMaxIdlePlayers) | |
202 CleanupIdleDelegates(idle_timeout_ / 10); | |
liberato (no reviews please)
2016/09/13 15:34:28
10?
DaleCurtis
2016/09/15 23:03:55
Just wanted something over 0, but now I don't see
| |
177 } | 203 } |
178 | 204 |
179 void RendererWebMediaPlayerDelegate::RemoveIdleDelegate(int delegate_id) { | 205 void RendererWebMediaPlayerDelegate::RemoveIdleDelegate(int delegate_id) { |
180 // To avoid invalidating the iterator, just mark the delegate for deletion | 206 // To avoid invalidating the iterator, just mark the delegate for deletion |
181 // using a sentinel value of an empty TimeTicks. | 207 // using a sentinel value of an empty TimeTicks. |
182 if (idle_cleanup_running_) { | 208 if (idle_cleanup_running_) { |
183 idle_delegate_map_[delegate_id] = base::TimeTicks(); | 209 idle_delegate_map_[delegate_id] = base::TimeTicks(); |
184 return; | 210 return; |
185 } | 211 } |
186 | 212 |
187 idle_delegate_map_.erase(delegate_id); | 213 idle_delegate_map_.erase(delegate_id); |
188 if (idle_delegate_map_.empty()) | 214 if (idle_delegate_map_.empty()) |
189 idle_cleanup_timer_.Stop(); | 215 idle_cleanup_timer_.Stop(); |
190 } | 216 } |
191 | 217 |
192 void RendererWebMediaPlayerDelegate::CleanupIdleDelegates() { | 218 void RendererWebMediaPlayerDelegate::CleanupIdleDelegates( |
219 base::TimeDelta idle_timeout) { | |
liberato (no reviews please)
2016/09/13 15:34:28
|idle_timeout| and |idle_timeout_| are a little co
DaleCurtis
2016/09/15 23:03:55
Done.
| |
193 // Iterate over the delegates and suspend the idle ones. Note: The call to | 220 // Iterate over the delegates and suspend the idle ones. Note: The call to |
194 // OnHidden() can trigger calls into RemoveIdleDelegate(), so for iterator | 221 // OnHidden() can trigger calls into RemoveIdleDelegate(), so for iterator |
195 // validity we set |idle_cleanup_running_| to true and defer deletions. | 222 // validity we set |idle_cleanup_running_| to true and defer deletions. |
196 base::AutoReset<bool> scoper(&idle_cleanup_running_, true); | 223 base::AutoReset<bool> scoper(&idle_cleanup_running_, true); |
197 const base::TimeTicks now = tick_clock_->NowTicks(); | 224 const base::TimeTicks now = tick_clock_->NowTicks(); |
198 for (auto& idle_delegate_entry : idle_delegate_map_) { | 225 for (auto& idle_delegate_entry : idle_delegate_map_) { |
199 if (now - idle_delegate_entry.second > idle_timeout_) { | 226 if (now - idle_delegate_entry.second > idle_timeout) { |
200 id_map_.Lookup(idle_delegate_entry.first)->OnSuspendRequested(false); | 227 id_map_.Lookup(idle_delegate_entry.first)->OnSuspendRequested(false); |
201 | 228 |
202 // Whether or not the player accepted the suspension, mark it for removal | 229 // Whether or not the player accepted the suspension, mark it for removal |
203 // from future polls to avoid running the timer forever. | 230 // from future polls to avoid running the timer forever. |
204 idle_delegate_entry.second = base::TimeTicks(); | 231 idle_delegate_entry.second = base::TimeTicks(); |
205 } | 232 } |
206 } | 233 } |
207 | 234 |
208 // Take care of any removals that happened during the above iteration. | 235 // Take care of any removals that happened during the above iteration. |
209 for (auto it = idle_delegate_map_.begin(); it != idle_delegate_map_.end();) { | 236 for (auto it = idle_delegate_map_.begin(); it != idle_delegate_map_.end();) { |
(...skipping 28 matching lines...) Expand all Loading... | |
238 #endif // OS_ANDROID | 265 #endif // OS_ANDROID |
239 | 266 |
240 is_playing_background_video_ = is_playing; | 267 is_playing_background_video_ = is_playing; |
241 } | 268 } |
242 | 269 |
243 void RendererWebMediaPlayerDelegate::OnDestruct() { | 270 void RendererWebMediaPlayerDelegate::OnDestruct() { |
244 delete this; | 271 delete this; |
245 } | 272 } |
246 | 273 |
247 } // namespace media | 274 } // namespace media |
OLD | NEW |