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

Side by Side Diff: content/browser/media/capture/aura_window_capture_machine.cc

Issue 1942493002: Short-term fix for Aura Desktop/Window capture. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2704
Patch Set: Created 4 years, 7 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
« no previous file with comments | « content/browser/media/capture/aura_window_capture_machine.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/browser/media/capture/aura_window_capture_machine.h" 5 #include "content/browser/media/capture/aura_window_capture_machine.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 return false; 73 return false;
74 74
75 DCHECK(oracle_proxy); 75 DCHECK(oracle_proxy);
76 oracle_proxy_ = oracle_proxy; 76 oracle_proxy_ = oracle_proxy;
77 capture_params_ = params; 77 capture_params_ = params;
78 78
79 // Update capture size. 79 // Update capture size.
80 UpdateCaptureSize(); 80 UpdateCaptureSize();
81 81
82 // Start observing compositor updates. 82 // Start observing compositor updates.
83 if (desktop_window_->GetHost()) 83 aura::WindowTreeHost* const host = desktop_window_->GetHost();
84 desktop_window_->GetHost()->compositor()->AddObserver(this); 84 ui::Compositor* const compositor = host ? host->compositor() : nullptr;
85 if (!compositor)
86 return false;
87 compositor->AddAnimationObserver(this);
85 88
86 power_save_blocker_.reset( 89 power_save_blocker_.reset(
87 PowerSaveBlocker::Create( 90 PowerSaveBlocker::Create(
88 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, 91 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
89 PowerSaveBlocker::kReasonOther, 92 PowerSaveBlocker::kReasonOther,
90 "DesktopCaptureDevice is running").release()); 93 "DesktopCaptureDevice is running").release());
91 94
92 return true; 95 return true;
93 } 96 }
94 97
95 void AuraWindowCaptureMachine::Stop(const base::Closure& callback) { 98 void AuraWindowCaptureMachine::Stop(const base::Closure& callback) {
96 // Stops the capture machine asynchronously. 99 // Stops the capture machine asynchronously.
97 BrowserThread::PostTask( 100 BrowserThread::PostTask(
98 BrowserThread::UI, FROM_HERE, base::Bind( 101 BrowserThread::UI, FROM_HERE, base::Bind(
99 &AuraWindowCaptureMachine::InternalStop, 102 &AuraWindowCaptureMachine::InternalStop,
100 base::Unretained(this), 103 base::Unretained(this),
101 callback)); 104 callback));
102 } 105 }
103 106
104 void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) { 107 void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) {
105 DCHECK_CURRENTLY_ON(BrowserThread::UI); 108 DCHECK_CURRENTLY_ON(BrowserThread::UI);
106 109
107 // Cancel any and all outstanding callbacks owned by external modules. 110 // Cancel any and all outstanding callbacks owned by external modules.
108 weak_factory_.InvalidateWeakPtrs(); 111 weak_factory_.InvalidateWeakPtrs();
109 112
110 power_save_blocker_.reset(); 113 power_save_blocker_.reset();
111 114
112 // Stop observing compositor and window events. 115 // Stop observing compositor and window events.
113 if (desktop_window_) { 116 if (desktop_window_) {
114 aura::WindowTreeHost* window_host = desktop_window_->GetHost(); 117 if (aura::WindowTreeHost* host = desktop_window_->GetHost()) {
115 // In the host destructor the compositor is destroyed before the window. 118 if (ui::Compositor* compositor = host->compositor())
116 if (window_host && window_host->compositor()) 119 compositor->RemoveAnimationObserver(this);
117 window_host->compositor()->RemoveObserver(this); 120 }
118 desktop_window_->RemoveObserver(this); 121 desktop_window_->RemoveObserver(this);
119 desktop_window_ = NULL; 122 desktop_window_ = NULL;
120 cursor_renderer_.reset(); 123 cursor_renderer_.reset();
121 } 124 }
122 125
123 callback.Run(); 126 callback.Run();
124 } 127 }
125 128
126 void AuraWindowCaptureMachine::MaybeCaptureForRefresh() { 129 void AuraWindowCaptureMachine::MaybeCaptureForRefresh() {
127 BrowserThread::PostTask( 130 BrowserThread::PostTask(
128 BrowserThread::UI, FROM_HERE, 131 BrowserThread::UI, FROM_HERE,
129 base::Bind(&AuraWindowCaptureMachine::Capture, 132 base::Bind(&AuraWindowCaptureMachine::Capture,
130 // Use of Unretained() is safe here since this task must run 133 // Use of Unretained() is safe here since this task must run
131 // before InternalStop(). 134 // before InternalStop().
132 base::Unretained(this), 135 base::Unretained(this),
133 false)); 136 base::TimeTicks()));
134 } 137 }
135 138
136 void AuraWindowCaptureMachine::SetWindow(aura::Window* window) { 139 void AuraWindowCaptureMachine::SetWindow(aura::Window* window) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI); 140 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138 141
139 DCHECK(!desktop_window_); 142 DCHECK(!desktop_window_);
140 desktop_window_ = window; 143 desktop_window_ = window;
141 cursor_renderer_.reset(new CursorRendererAura(window, kCursorAlwaysEnabled)); 144 cursor_renderer_.reset(new CursorRendererAura(window, kCursorAlwaysEnabled));
142 145
143 // Start observing window events. 146 // Start observing window events.
144 desktop_window_->AddObserver(this); 147 desktop_window_->AddObserver(this);
145 148
146 // We must store this for the UMA reporting in DidCopyOutput() as 149 // We must store this for the UMA reporting in DidCopyOutput() as
147 // desktop_window_ might be destroyed at that point. 150 // desktop_window_ might be destroyed at that point.
148 screen_capture_ = window->IsRootWindow(); 151 screen_capture_ = window->IsRootWindow();
149 IncrementDesktopCaptureCounter(screen_capture_ ? SCREEN_CAPTURER_CREATED 152 IncrementDesktopCaptureCounter(screen_capture_ ? SCREEN_CAPTURER_CREATED
150 : WINDOW_CAPTURER_CREATED); 153 : WINDOW_CAPTURER_CREATED);
151 } 154 }
152 155
153 void AuraWindowCaptureMachine::UpdateCaptureSize() { 156 void AuraWindowCaptureMachine::UpdateCaptureSize() {
154 DCHECK_CURRENTLY_ON(BrowserThread::UI); 157 DCHECK_CURRENTLY_ON(BrowserThread::UI);
155 if (oracle_proxy_ && desktop_window_) { 158 if (oracle_proxy_ && desktop_window_) {
156 ui::Layer* layer = desktop_window_->layer(); 159 ui::Layer* layer = desktop_window_->layer();
157 oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel( 160 oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
158 layer, layer->bounds().size())); 161 layer, layer->bounds().size()));
159 } 162 }
160 cursor_renderer_->Clear(); 163 cursor_renderer_->Clear();
161 } 164 }
162 165
163 void AuraWindowCaptureMachine::Capture(bool dirty) { 166 void AuraWindowCaptureMachine::Capture(base::TimeTicks event_time) {
164 DCHECK_CURRENTLY_ON(BrowserThread::UI); 167 DCHECK_CURRENTLY_ON(BrowserThread::UI);
165 168
166 // Do not capture if the desktop window is already destroyed. 169 // Do not capture if the desktop window is already destroyed.
167 if (!desktop_window_) 170 if (!desktop_window_)
168 return; 171 return;
169 172
170 scoped_refptr<media::VideoFrame> frame; 173 scoped_refptr<media::VideoFrame> frame;
171 media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; 174 media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
172 175
173 // TODO(miu): Need to fix this so the compositor is providing the presentation 176 // TODO(miu): Need to fix this so the compositor is providing the presentation
174 // timestamps and damage regions, to leverage the frame timestamp rewriting 177 // timestamps and damage regions, to leverage the frame timestamp rewriting
175 // logic. http://crbug.com/492839 178 // logic. http://crbug.com/492839
176 const base::TimeTicks start_time = base::TimeTicks::Now(); 179 const base::TimeTicks start_time = base::TimeTicks::Now();
177 const media::VideoCaptureOracle::Event event = 180 media::VideoCaptureOracle::Event event;
178 dirty ? media::VideoCaptureOracle::kCompositorUpdate 181 if (event_time.is_null()) {
179 : media::VideoCaptureOracle::kActiveRefreshRequest; 182 event = media::VideoCaptureOracle::kActiveRefreshRequest;
183 event_time = start_time;
184 } else {
185 event = media::VideoCaptureOracle::kCompositorUpdate;
186 }
180 if (oracle_proxy_->ObserveEventAndDecideCapture( 187 if (oracle_proxy_->ObserveEventAndDecideCapture(
181 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { 188 event, gfx::Rect(), event_time, &frame, &capture_frame_cb)) {
182 std::unique_ptr<cc::CopyOutputRequest> request = 189 std::unique_ptr<cc::CopyOutputRequest> request =
183 cc::CopyOutputRequest::CreateRequest(base::Bind( 190 cc::CopyOutputRequest::CreateRequest(base::Bind(
184 &AuraWindowCaptureMachine::DidCopyOutput, 191 &AuraWindowCaptureMachine::DidCopyOutput,
185 weak_factory_.GetWeakPtr(), frame, start_time, capture_frame_cb)); 192 weak_factory_.GetWeakPtr(), frame, event_time, start_time,
193 capture_frame_cb));
186 gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(), 194 gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(),
187 desktop_window_->bounds().height()); 195 desktop_window_->bounds().height());
188 request->set_area(window_rect); 196 request->set_area(window_rect);
189 desktop_window_->layer()->RequestCopyOfOutput(std::move(request)); 197 desktop_window_->layer()->RequestCopyOfOutput(std::move(request));
190 } 198 }
191 } 199 }
192 200
193 void AuraWindowCaptureMachine::DidCopyOutput( 201 void AuraWindowCaptureMachine::DidCopyOutput(
194 scoped_refptr<media::VideoFrame> video_frame, 202 scoped_refptr<media::VideoFrame> video_frame,
203 base::TimeTicks event_time,
195 base::TimeTicks start_time, 204 base::TimeTicks start_time,
196 const CaptureFrameCallback& capture_frame_cb, 205 const CaptureFrameCallback& capture_frame_cb,
197 std::unique_ptr<cc::CopyOutputResult> result) { 206 std::unique_ptr<cc::CopyOutputResult> result) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 207 DCHECK_CURRENTLY_ON(BrowserThread::UI);
199 208
200 static bool first_call = true; 209 static bool first_call = true;
201 210
202 const bool succeeded = ProcessCopyOutputResponse( 211 const bool succeeded = ProcessCopyOutputResponse(
203 video_frame, start_time, capture_frame_cb, std::move(result)); 212 video_frame, event_time, capture_frame_cb, std::move(result));
204 213
205 base::TimeDelta capture_time = base::TimeTicks::Now() - start_time; 214 const base::TimeDelta capture_time = base::TimeTicks::Now() - start_time;
206 215
207 // The two UMA_ blocks must be put in its own scope since it creates a static 216 // The two UMA_ blocks must be put in its own scope since it creates a static
208 // variable which expected constant histogram name. 217 // variable which expected constant histogram name.
209 if (screen_capture_) { 218 if (screen_capture_) {
210 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time); 219 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
211 } else { 220 } else {
212 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time); 221 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
213 } 222 }
214 223
215 if (first_call) { 224 if (first_call) {
216 first_call = false; 225 first_call = false;
217 if (screen_capture_) { 226 if (screen_capture_) {
218 IncrementDesktopCaptureCounter(succeeded ? FIRST_SCREEN_CAPTURE_SUCCEEDED 227 IncrementDesktopCaptureCounter(succeeded ? FIRST_SCREEN_CAPTURE_SUCCEEDED
219 : FIRST_SCREEN_CAPTURE_FAILED); 228 : FIRST_SCREEN_CAPTURE_FAILED);
220 } else { 229 } else {
221 IncrementDesktopCaptureCounter(succeeded 230 IncrementDesktopCaptureCounter(succeeded
222 ? FIRST_WINDOW_CAPTURE_SUCCEEDED 231 ? FIRST_WINDOW_CAPTURE_SUCCEEDED
223 : FIRST_WINDOW_CAPTURE_FAILED); 232 : FIRST_WINDOW_CAPTURE_FAILED);
224 } 233 }
225 } 234 }
226 235
227 // If ProcessCopyOutputResponse() failed, it will not run |capture_frame_cb|, 236 // If ProcessCopyOutputResponse() failed, it will not run |capture_frame_cb|,
228 // so do that now. 237 // so do that now.
229 if (!succeeded) 238 if (!succeeded)
230 capture_frame_cb.Run(video_frame, start_time, false); 239 capture_frame_cb.Run(video_frame, event_time, false);
231 } 240 }
232 241
233 bool AuraWindowCaptureMachine::ProcessCopyOutputResponse( 242 bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
234 scoped_refptr<media::VideoFrame> video_frame, 243 scoped_refptr<media::VideoFrame> video_frame,
235 base::TimeTicks start_time, 244 base::TimeTicks event_time,
236 const CaptureFrameCallback& capture_frame_cb, 245 const CaptureFrameCallback& capture_frame_cb,
237 std::unique_ptr<cc::CopyOutputResult> result) { 246 std::unique_ptr<cc::CopyOutputResult> result) {
238 DCHECK_CURRENTLY_ON(BrowserThread::UI); 247 DCHECK_CURRENTLY_ON(BrowserThread::UI);
239 248
240 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_window_) 249 if (!desktop_window_) {
250 VLOG(1) << "Ignoring CopyOutputResult: Capture target has gone away.";
241 return false; 251 return false;
252 }
253 if (result->IsEmpty()) {
254 VLOG(1) << "CopyOutputRequest failed: No texture or bitmap in result.";
255 return false;
256 }
257 if (result->size().IsEmpty()) {
258 VLOG(1) << "CopyOutputRequest failed: Zero-area texture/bitmap result.";
259 return false;
260 }
242 DCHECK(video_frame); 261 DCHECK(video_frame);
243 262
244 // Compute the dest size we want after the letterboxing resize. Make the 263 // Compute the dest size we want after the letterboxing resize. Make the
245 // coordinates and sizes even because we letterbox in YUV space 264 // coordinates and sizes even because we letterbox in YUV space
246 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to 265 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
247 // line up correctly. 266 // line up correctly.
248 // The video frame's visible_rect() and the result's size() are both physical 267 // The video frame's visible_rect() and the result's size() are both physical
249 // pixels. 268 // pixels.
250 gfx::Rect region_in_frame = media::ComputeLetterboxRegion( 269 gfx::Rect region_in_frame = media::ComputeLetterboxRegion(
251 video_frame->visible_rect(), result->size()); 270 video_frame->visible_rect(), result->size());
252 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, 271 region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
253 region_in_frame.y() & ~1, 272 region_in_frame.y() & ~1,
254 region_in_frame.width() & ~1, 273 region_in_frame.width() & ~1,
255 region_in_frame.height() & ~1); 274 region_in_frame.height() & ~1);
256 if (region_in_frame.IsEmpty()) 275 if (region_in_frame.IsEmpty()) {
276 VLOG(1) << "Aborting capture: Computed empty letterboxed content region.";
257 return false; 277 return false;
278 }
258 279
259 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 280 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
260 GLHelper* gl_helper = factory->GetGLHelper(); 281 GLHelper* gl_helper = factory->GetGLHelper();
261 if (!gl_helper) 282 if (!gl_helper) {
283 VLOG(1) << "Aborting capture: No GLHelper available for YUV readback.";
262 return false; 284 return false;
285 }
263 286
264 cc::TextureMailbox texture_mailbox; 287 cc::TextureMailbox texture_mailbox;
265 std::unique_ptr<cc::SingleReleaseCallback> release_callback; 288 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
266 result->TakeTexture(&texture_mailbox, &release_callback); 289 result->TakeTexture(&texture_mailbox, &release_callback);
267 DCHECK(texture_mailbox.IsTexture()); 290 DCHECK(texture_mailbox.IsTexture());
268 if (!texture_mailbox.IsTexture()) 291 if (!texture_mailbox.IsTexture()) {
292 VLOG(1) << "Aborting capture: Failed to take texture from mailbox.";
269 return false; 293 return false;
294 }
270 295
271 gfx::Rect result_rect(result->size()); 296 gfx::Rect result_rect(result->size());
272 if (!yuv_readback_pipeline_ || 297 if (!yuv_readback_pipeline_ ||
273 yuv_readback_pipeline_->scaler()->SrcSize() != result_rect.size() || 298 yuv_readback_pipeline_->scaler()->SrcSize() != result_rect.size() ||
274 yuv_readback_pipeline_->scaler()->SrcSubrect() != result_rect || 299 yuv_readback_pipeline_->scaler()->SrcSubrect() != result_rect ||
275 yuv_readback_pipeline_->scaler()->DstSize() != region_in_frame.size()) { 300 yuv_readback_pipeline_->scaler()->DstSize() != region_in_frame.size()) {
276 yuv_readback_pipeline_.reset( 301 yuv_readback_pipeline_.reset(
277 gl_helper->CreateReadbackPipelineYUV(GLHelper::SCALER_QUALITY_FAST, 302 gl_helper->CreateReadbackPipelineYUV(GLHelper::SCALER_QUALITY_FAST,
278 result_rect.size(), 303 result_rect.size(),
279 result_rect, 304 result_rect,
280 region_in_frame.size(), 305 region_in_frame.size(),
281 true, 306 true,
282 true)); 307 true));
283 } 308 }
284 309
285 cursor_renderer_->SnapshotCursorState(region_in_frame); 310 cursor_renderer_->SnapshotCursorState(region_in_frame);
286 yuv_readback_pipeline_->ReadbackYUV( 311 yuv_readback_pipeline_->ReadbackYUV(
287 texture_mailbox.mailbox(), texture_mailbox.sync_token(), 312 texture_mailbox.mailbox(), texture_mailbox.sync_token(),
288 video_frame.get(), region_in_frame.origin(), 313 video_frame.get(), region_in_frame.origin(),
289 base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(), 314 base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(),
290 start_time, capture_frame_cb, video_frame, 315 event_time, capture_frame_cb, video_frame,
291 base::Passed(&release_callback))); 316 base::Passed(&release_callback)));
292 return true; 317 return true;
293 } 318 }
294 319
295 using CaptureFrameCallback = 320 using CaptureFrameCallback =
296 media::ThreadSafeCaptureOracle::CaptureFrameCallback; 321 media::ThreadSafeCaptureOracle::CaptureFrameCallback;
297 322
298 void AuraWindowCaptureMachine::CopyOutputFinishedForVideo( 323 void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
299 base::WeakPtr<AuraWindowCaptureMachine> machine, 324 base::WeakPtr<AuraWindowCaptureMachine> machine,
300 base::TimeTicks start_time, 325 base::TimeTicks event_time,
301 const CaptureFrameCallback& capture_frame_cb, 326 const CaptureFrameCallback& capture_frame_cb,
302 const scoped_refptr<media::VideoFrame>& target, 327 const scoped_refptr<media::VideoFrame>& target,
303 std::unique_ptr<cc::SingleReleaseCallback> release_callback, 328 std::unique_ptr<cc::SingleReleaseCallback> release_callback,
304 bool result) { 329 bool result) {
305 DCHECK_CURRENTLY_ON(BrowserThread::UI); 330 DCHECK_CURRENTLY_ON(BrowserThread::UI);
306 331
307 release_callback->Run(gpu::SyncToken(), false); 332 release_callback->Run(gpu::SyncToken(), false);
308 333
309 // Render the cursor and deliver the captured frame if the 334 // Render the cursor and deliver the captured frame if the
310 // AuraWindowCaptureMachine has not been stopped (i.e., the WeakPtr is 335 // AuraWindowCaptureMachine has not been stopped (i.e., the WeakPtr is
311 // still valid). 336 // still valid).
312 if (machine) { 337 if (machine) {
313 if (machine->cursor_renderer_ && result) 338 if (machine->cursor_renderer_ && result)
314 machine->cursor_renderer_->RenderOnVideoFrame(target); 339 machine->cursor_renderer_->RenderOnVideoFrame(target);
315 } else { 340 } else {
341 VLOG(1) << "Aborting capture: AuraWindowCaptureMachine has gone away.";
316 result = false; 342 result = false;
317 } 343 }
318 344
319 capture_frame_cb.Run(target, start_time, result); 345 capture_frame_cb.Run(target, event_time, result);
320 } 346 }
321 347
322 void AuraWindowCaptureMachine::OnWindowBoundsChanged( 348 void AuraWindowCaptureMachine::OnWindowBoundsChanged(
323 aura::Window* window, 349 aura::Window* window,
324 const gfx::Rect& old_bounds, 350 const gfx::Rect& old_bounds,
325 const gfx::Rect& new_bounds) { 351 const gfx::Rect& new_bounds) {
326 DCHECK_CURRENTLY_ON(BrowserThread::UI); 352 DCHECK_CURRENTLY_ON(BrowserThread::UI);
327 DCHECK(desktop_window_ && window == desktop_window_); 353 DCHECK(desktop_window_ && window == desktop_window_);
328 354
329 // Post a task to update capture size after first returning to the event loop. 355 // Post a task to update capture size after first returning to the event loop.
330 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 356 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
331 &AuraWindowCaptureMachine::UpdateCaptureSize, 357 &AuraWindowCaptureMachine::UpdateCaptureSize,
332 weak_factory_.GetWeakPtr())); 358 weak_factory_.GetWeakPtr()));
333 } 359 }
334 360
335 void AuraWindowCaptureMachine::OnWindowDestroying(aura::Window* window) { 361 void AuraWindowCaptureMachine::OnWindowDestroying(aura::Window* window) {
336 DCHECK_CURRENTLY_ON(BrowserThread::UI); 362 DCHECK_CURRENTLY_ON(BrowserThread::UI);
337 363
338 InternalStop(base::Bind(&base::DoNothing)); 364 InternalStop(base::Bind(&base::DoNothing));
339 365
340 oracle_proxy_->ReportError(FROM_HERE, "OnWindowDestroying()"); 366 oracle_proxy_->ReportError(FROM_HERE, "OnWindowDestroying()");
341 } 367 }
342 368
343 void AuraWindowCaptureMachine::OnWindowAddedToRootWindow( 369 void AuraWindowCaptureMachine::OnWindowAddedToRootWindow(
344 aura::Window* window) { 370 aura::Window* window) {
345 DCHECK_CURRENTLY_ON(BrowserThread::UI); 371 DCHECK_CURRENTLY_ON(BrowserThread::UI);
346 DCHECK(window == desktop_window_); 372 DCHECK(window == desktop_window_);
347 373
348 window->GetHost()->compositor()->AddObserver(this); 374 if (aura::WindowTreeHost* host = window->GetHost()) {
375 if (ui::Compositor* compositor = host->compositor())
376 compositor->AddAnimationObserver(this);
377 }
349 } 378 }
350 379
351 void AuraWindowCaptureMachine::OnWindowRemovingFromRootWindow( 380 void AuraWindowCaptureMachine::OnWindowRemovingFromRootWindow(
352 aura::Window* window, 381 aura::Window* window,
353 aura::Window* new_root) { 382 aura::Window* new_root) {
354 DCHECK_CURRENTLY_ON(BrowserThread::UI); 383 DCHECK_CURRENTLY_ON(BrowserThread::UI);
355 DCHECK(window == desktop_window_); 384 DCHECK(window == desktop_window_);
356 385
357 window->GetHost()->compositor()->RemoveObserver(this); 386 if (aura::WindowTreeHost* host = window->GetHost()) {
387 if (ui::Compositor* compositor = host->compositor())
388 compositor->RemoveAnimationObserver(this);
389 }
358 } 390 }
359 391
360 void AuraWindowCaptureMachine::OnCompositingEnded( 392 void AuraWindowCaptureMachine::OnAnimationStep(base::TimeTicks timestamp) {
393 DCHECK_CURRENTLY_ON(BrowserThread::UI);
394 DCHECK(!timestamp.is_null());
395
396 // HACK: The compositor invokes this observer method to step layer animation
397 // forward. Scheduling frame capture was not the intention, and so invoking
398 // this method does not actually indicate the content has changed. However,
399 // this is the only reliable way to ensure all screen changes are captured, as
400 // of this writing.
401 // http://crbug.com/600031
402 //
403 // TODO(miu): Need a better observer callback interface from the compositor
404 // for this use case. The solution here will always capture frames at the
405 // maximum framerate, which means CPU/GPU is being wasted on redundant
406 // captures and quality/smoothness of animating content will suffer
407 // significantly.
408 // http://crbug.com/492839
409 Capture(timestamp);
410 }
411
412 void AuraWindowCaptureMachine::OnCompositingShuttingDown(
361 ui::Compositor* compositor) { 413 ui::Compositor* compositor) {
362 DCHECK_CURRENTLY_ON(BrowserThread::UI); 414 DCHECK_CURRENTLY_ON(BrowserThread::UI);
363 415 compositor->RemoveAnimationObserver(this);
364 // TODO(miu): The CopyOutputRequest should be made earlier, at WillCommit().
365 // http://crbug.com/492839
366 BrowserThread::PostTask(
367 BrowserThread::UI,
368 FROM_HERE,
369 base::Bind(&AuraWindowCaptureMachine::Capture, weak_factory_.GetWeakPtr(),
370 true));
371 } 416 }
372 417
373 } // namespace content 418 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/capture/aura_window_capture_machine.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698