Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: content/renderer/pepper/plugin_instance_throttler_impl.cc

Issue 879403002: Plugin Power Saver: Mute throttled plugins. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove hack used for testing. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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/pepper/plugin_instance_throttler_impl.h" 5 #include "content/renderer/pepper/plugin_instance_throttler_impl.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/time/time.h" 8 #include "base/time/time.h"
9 #include "content/public/common/content_constants.h" 9 #include "content/public/common/content_constants.h"
10 #include "content/public/renderer/render_thread.h" 10 #include "content/public/renderer/render_thread.h"
11 #include "content/renderer/render_frame_impl.h" 11 #include "content/renderer/render_frame_impl.h"
12 #include "third_party/WebKit/public/platform/WebRect.h" 12 #include "third_party/WebKit/public/platform/WebRect.h"
13 #include "third_party/WebKit/public/web/WebInputEvent.h" 13 #include "third_party/WebKit/public/web/WebInputEvent.h"
14 #include "third_party/WebKit/public/web/WebPluginParams.h" 14 #include "third_party/WebKit/public/web/WebPluginParams.h"
15 #include "ui/gfx/color_utils.h" 15 #include "ui/gfx/color_utils.h"
16 #include "url/gurl.h" 16 #include "url/gurl.h"
17 17
18 namespace content { 18 namespace content {
19 19
20 namespace { 20 namespace {
21 21
22 // Threshold for 'boring' score to accept a frame as good enough to be a 22 // Threshold for 'boring' score to accept a frame as good enough to be a
23 // representative keyframe. Units are the ratio of all pixels that are within 23 // representative keyframe. Units are the ratio of all pixels that are within
24 // the most common luma bin. The same threshold is used for history thumbnails. 24 // the most common luma bin. The same threshold is used for history thumbnails.
25 const double kAcceptableFrameMaximumBoringness = 0.94; 25 const double kAcceptableFrameMaximumBoringness = 0.94;
26 26
27 const int kMinimumConsecutiveInterestingFrames = 4; 27 const int kMinimumConsecutiveInterestingFrames = 4;
28 28
29 // When plugin audio is throttled, the plugin will sometimes stop generating
30 // video frames. We use this timeout to prevent waiting forever for a good
31 // poster image. Chosen arbitrarily.
32 const int kAudioThrottledFrameTimeoutMilliseconds = 500;
33
29 } // namespace 34 } // namespace
30 35
31 // static 36 // static
32 const int PluginInstanceThrottlerImpl::kMaximumFramesToExamine = 150; 37 const int PluginInstanceThrottlerImpl::kMaximumFramesToExamine = 150;
33 38
34 // static 39 // static
35 scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Create( 40 scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Create(
36 bool power_saver_enabled) { 41 bool power_saver_enabled) {
37 return make_scoped_ptr(new PluginInstanceThrottlerImpl(power_saver_enabled)); 42 return make_scoped_ptr(new PluginInstanceThrottlerImpl(power_saver_enabled));
38 } 43 }
39 44
40 // static 45 // static
41 void PluginInstanceThrottler::RecordUnthrottleMethodMetric( 46 void PluginInstanceThrottler::RecordUnthrottleMethodMetric(
42 PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) { 47 PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) {
43 UMA_HISTOGRAM_ENUMERATION( 48 UMA_HISTOGRAM_ENUMERATION(
44 "Plugin.PowerSaver.Unthrottle", method, 49 "Plugin.PowerSaver.Unthrottle", method,
45 PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS); 50 PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS);
46 } 51 }
47 52
48 PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl( 53 PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl(
49 bool power_saver_enabled) 54 bool power_saver_enabled)
50 : state_(power_saver_enabled ? THROTTLER_STATE_AWAITING_KEYFRAME 55 : state_(power_saver_enabled ? THROTTLER_STATE_AWAITING_KEYFRAME
51 : THROTTLER_STATE_POWER_SAVER_DISABLED), 56 : THROTTLER_STATE_POWER_SAVER_DISABLED),
52 is_hidden_for_placeholder_(false), 57 is_hidden_for_placeholder_(false),
53 web_plugin_(nullptr), 58 web_plugin_(nullptr),
54 consecutive_interesting_frames_(0), 59 consecutive_interesting_frames_(0),
55 frames_examined_(0), 60 frames_examined_(0),
61 audio_throttled_(false),
62 audio_throttled_frame_timeout_(
63 FROM_HERE,
64 base::TimeDelta::FromMilliseconds(
65 kAudioThrottledFrameTimeoutMilliseconds),
66 this,
67 &PluginInstanceThrottlerImpl::EngageThrottle),
56 weak_factory_(this) { 68 weak_factory_(this) {
57 } 69 }
58 70
59 PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() { 71 PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() {
60 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottlerDestroyed()); 72 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottlerDestroyed());
61 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL) 73 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL)
62 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER); 74 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER);
63 } 75 }
64 76
65 void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) { 77 void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) {
(...skipping 28 matching lines...) Expand all
94 void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) { 106 void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) {
95 is_hidden_for_placeholder_ = hidden; 107 is_hidden_for_placeholder_ = hidden;
96 FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden)); 108 FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden));
97 } 109 }
98 110
99 blink::WebPlugin* PluginInstanceThrottlerImpl::GetWebPlugin() const { 111 blink::WebPlugin* PluginInstanceThrottlerImpl::GetWebPlugin() const {
100 DCHECK(web_plugin_); 112 DCHECK(web_plugin_);
101 return web_plugin_; 113 return web_plugin_;
102 } 114 }
103 115
116 void PluginInstanceThrottlerImpl::NotifyAudioThrottled() {
117 audio_throttled_ = true;
118 audio_throttled_frame_timeout_.Reset();
119 }
120
104 void PluginInstanceThrottlerImpl::SetWebPlugin(blink::WebPlugin* web_plugin) { 121 void PluginInstanceThrottlerImpl::SetWebPlugin(blink::WebPlugin* web_plugin) {
105 DCHECK(!web_plugin_); 122 DCHECK(!web_plugin_);
106 web_plugin_ = web_plugin; 123 web_plugin_ = web_plugin;
107 } 124 }
108 125
109 void PluginInstanceThrottlerImpl::Initialize( 126 void PluginInstanceThrottlerImpl::Initialize(
110 RenderFrameImpl* frame, 127 RenderFrameImpl* frame,
111 const GURL& content_origin, 128 const GURL& content_origin,
112 const std::string& plugin_module_name, 129 const std::string& plugin_module_name,
113 const blink::WebRect& bounds) { 130 const blink::WebRect& bounds) {
(...skipping 27 matching lines...) Expand all
141 return; 158 return;
142 159
143 ++frames_examined_; 160 ++frames_examined_;
144 161
145 double boring_score = color_utils::CalculateBoringScore(*bitmap); 162 double boring_score = color_utils::CalculateBoringScore(*bitmap);
146 if (boring_score <= kAcceptableFrameMaximumBoringness) 163 if (boring_score <= kAcceptableFrameMaximumBoringness)
147 ++consecutive_interesting_frames_; 164 ++consecutive_interesting_frames_;
148 else 165 else
149 consecutive_interesting_frames_ = 0; 166 consecutive_interesting_frames_ = 0;
150 167
168 // Does not make a copy, just takes a reference to the underlying pixel data.
169 last_received_frame_ = *bitmap;
170
171 if (audio_throttled_)
172 audio_throttled_frame_timeout_.Reset();
173
151 if (frames_examined_ >= kMaximumFramesToExamine || 174 if (frames_examined_ >= kMaximumFramesToExamine ||
152 consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames) { 175 consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames) {
153 FOR_EACH_OBSERVER(Observer, observer_list_, OnKeyframeExtracted(bitmap));
154 EngageThrottle(); 176 EngageThrottle();
155 } 177 }
156 } 178 }
157 179
158 bool PluginInstanceThrottlerImpl::ConsumeInputEvent( 180 bool PluginInstanceThrottlerImpl::ConsumeInputEvent(
159 const blink::WebInputEvent& event) { 181 const blink::WebInputEvent& event) {
160 // Always allow right-clicks through so users may verify it's a plugin. 182 // Always allow right-clicks through so users may verify it's a plugin.
161 // TODO(tommycli): We should instead show a custom context menu (probably 183 // TODO(tommycli): We should instead show a custom context menu (probably
162 // using PluginPlaceholder) so users aren't confused and try to click the 184 // using PluginPlaceholder) so users aren't confused and try to click the
163 // Flash-internal 'Play' menu item. This is a stopgap solution. 185 // Flash-internal 'Play' menu item. This is a stopgap solution.
164 if (event.modifiers & blink::WebInputEvent::Modifiers::RightButtonDown) 186 if (event.modifiers & blink::WebInputEvent::Modifiers::RightButtonDown)
165 return false; 187 return false;
166 188
167 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL && 189 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL &&
168 event.type == blink::WebInputEvent::MouseUp && 190 event.type == blink::WebInputEvent::MouseUp &&
169 (event.modifiers & blink::WebInputEvent::LeftButtonDown)) { 191 (event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
170 bool was_throttled = IsThrottled(); 192 bool was_throttled = IsThrottled();
171 MarkPluginEssential(UNTHROTTLE_METHOD_BY_CLICK); 193 MarkPluginEssential(UNTHROTTLE_METHOD_BY_CLICK);
172 return was_throttled; 194 return was_throttled;
173 } 195 }
174 196
175 return IsThrottled(); 197 return IsThrottled();
176 } 198 }
177 199
178 void PluginInstanceThrottlerImpl::EngageThrottle() { 200 void PluginInstanceThrottlerImpl::EngageThrottle() {
179 if (state_ != THROTTLER_STATE_AWAITING_KEYFRAME) 201 if (state_ != THROTTLER_STATE_AWAITING_KEYFRAME)
180 return; 202 return;
181 203
204 if (!last_received_frame_.empty()) {
205 FOR_EACH_OBSERVER(Observer, observer_list_,
206 OnKeyframeExtracted(&last_received_frame_));
207
208 // Release our reference to the underlying pixel data.
209 last_received_frame_.reset();
210 }
211
182 state_ = THROTTLER_STATE_PLUGIN_THROTTLED; 212 state_ = THROTTLER_STATE_PLUGIN_THROTTLED;
183 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange()); 213 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
184 } 214 }
185 215
186 } // namespace content 216 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/plugin_instance_throttler_impl.h ('k') | content/renderer/pepper/ppb_audio_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698