Chromium Code Reviews| 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 |