OLD | NEW |
---|---|
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/browser/devtools/protocol/page_handler.h" | 5 #include "content/browser/devtools/protocol/page_handler.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 } // namespace | 89 } // namespace |
90 | 90 |
91 typedef DevToolsProtocolClient::Response Response; | 91 typedef DevToolsProtocolClient::Response Response; |
92 | 92 |
93 PageHandler::PageHandler() | 93 PageHandler::PageHandler() |
94 : enabled_(false), | 94 : enabled_(false), |
95 screencast_enabled_(false), | 95 screencast_enabled_(false), |
96 screencast_quality_(kDefaultScreenshotQuality), | 96 screencast_quality_(kDefaultScreenshotQuality), |
97 screencast_max_width_(-1), | 97 screencast_max_width_(-1), |
98 screencast_max_height_(-1), | 98 screencast_max_height_(-1), |
99 capture_every_nth_frame_(1), | |
99 capture_retry_count_(0), | 100 capture_retry_count_(0), |
100 has_compositor_frame_metadata_(false), | 101 has_compositor_frame_metadata_(false), |
101 screencast_frame_sent_(0), | 102 screencast_frame_sent_(0), |
102 screencast_frame_acked_(0), | 103 screencast_frame_acked_(0), |
103 processing_screencast_frame_(false), | |
104 color_picker_(new ColorPicker(base::Bind( | 104 color_picker_(new ColorPicker(base::Bind( |
105 &PageHandler::OnColorPicked, base::Unretained(this)))), | 105 &PageHandler::OnColorPicked, base::Unretained(this)))), |
106 host_(nullptr), | 106 host_(nullptr), |
107 weak_factory_(this) { | 107 weak_factory_(this) { |
108 } | 108 } |
109 | 109 |
110 PageHandler::~PageHandler() { | 110 PageHandler::~PageHandler() { |
111 } | 111 } |
112 | 112 |
113 void PageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { | 113 void PageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 *result = true; | 281 *result = true; |
282 #else | 282 #else |
283 *result = false; | 283 *result = false; |
284 #endif // defined(OS_ANDROID) | 284 #endif // defined(OS_ANDROID) |
285 return Response::OK(); | 285 return Response::OK(); |
286 } | 286 } |
287 | 287 |
288 Response PageHandler::StartScreencast(const std::string* format, | 288 Response PageHandler::StartScreencast(const std::string* format, |
289 const int* quality, | 289 const int* quality, |
290 const int* max_width, | 290 const int* max_width, |
291 const int* max_height) { | 291 const int* max_height, |
292 const int* every_nth_frame) { | |
292 RenderWidgetHostImpl* widget_host = | 293 RenderWidgetHostImpl* widget_host = |
293 host_ ? host_->GetRenderWidgetHost() : nullptr; | 294 host_ ? host_->GetRenderWidgetHost() : nullptr; |
294 if (!widget_host) | 295 if (!widget_host) |
295 return Response::InternalError("Could not connect to view"); | 296 return Response::InternalError("Could not connect to view"); |
296 | 297 |
297 screencast_enabled_ = true; | 298 screencast_enabled_ = true; |
298 screencast_format_ = format ? *format : kPng; | 299 screencast_format_ = format ? *format : kPng; |
299 screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality; | 300 screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality; |
300 if (screencast_quality_ < 0 || screencast_quality_ > 100) | 301 if (screencast_quality_ < 0 || screencast_quality_ > 100) |
301 screencast_quality_ = kDefaultScreenshotQuality; | 302 screencast_quality_ = kDefaultScreenshotQuality; |
302 screencast_max_width_ = max_width ? *max_width : -1; | 303 screencast_max_width_ = max_width ? *max_width : -1; |
303 screencast_max_height_ = max_height ? *max_height : -1; | 304 screencast_max_height_ = max_height ? *max_height : -1; |
305 screencast_frame_acked_ = screencast_frame_sent_; | |
306 capture_every_nth_frame_ = every_nth_frame ? *every_nth_frame : 1; | |
304 | 307 |
305 bool visible = !widget_host->is_hidden(); | 308 bool visible = !widget_host->is_hidden(); |
306 NotifyScreencastVisibility(visible); | 309 NotifyScreencastVisibility(visible); |
307 if (visible) { | 310 if (visible) { |
308 if (has_compositor_frame_metadata_) { | 311 if (has_compositor_frame_metadata_) { |
309 InnerSwapCompositorFrame(); | 312 InnerSwapCompositorFrame(); |
310 } else { | 313 } else { |
311 widget_host->Send( | 314 widget_host->Send( |
312 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); | 315 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); |
313 } | 316 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 } | 368 } |
366 | 369 |
367 void PageHandler::NotifyScreencastVisibility(bool visible) { | 370 void PageHandler::NotifyScreencastVisibility(bool visible) { |
368 if (visible) | 371 if (visible) |
369 capture_retry_count_ = kCaptureRetryLimit; | 372 capture_retry_count_ = kCaptureRetryLimit; |
370 client_->ScreencastVisibilityChanged( | 373 client_->ScreencastVisibilityChanged( |
371 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); | 374 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); |
372 } | 375 } |
373 | 376 |
374 void PageHandler::InnerSwapCompositorFrame() { | 377 void PageHandler::InnerSwapCompositorFrame() { |
378 if (!host_ || !host_->GetView()) | |
379 return; | |
380 | |
375 if (screencast_frame_sent_ - screencast_frame_acked_ > | 381 if (screencast_frame_sent_ - screencast_frame_acked_ > |
376 kMaxScreencastFramesInFlight || processing_screencast_frame_) { | 382 kMaxScreencastFramesInFlight) { |
377 return; | 383 return; |
378 } | 384 } |
379 | 385 |
380 if (!host_ || !host_->GetView()) | 386 static int global_frame_counter = 0; |
dgozman
2015/11/20 22:53:23
With two different screencasts active it may happe
pfeldman
2015/11/20 23:18:25
Yep.
| |
387 if (++global_frame_counter % capture_every_nth_frame_) | |
381 return; | 388 return; |
382 | 389 |
383 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 390 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
384 host_->GetView()); | 391 host_->GetView()); |
385 // TODO(vkuzkokov): do not use previous frame metadata. | 392 // TODO(vkuzkokov): do not use previous frame metadata. |
386 cc::CompositorFrameMetadata& metadata = last_compositor_frame_metadata_; | 393 cc::CompositorFrameMetadata& metadata = last_compositor_frame_metadata_; |
387 | 394 |
388 gfx::SizeF viewport_size_dip = gfx::ScaleSize( | 395 gfx::SizeF viewport_size_dip = gfx::ScaleSize( |
389 metadata.scrollable_viewport_size, metadata.page_scale_factor); | 396 metadata.scrollable_viewport_size, metadata.page_scale_factor); |
390 gfx::SizeF screen_size_dip = | 397 gfx::SizeF screen_size_dip = |
(...skipping 14 matching lines...) Expand all Loading... | |
405 scale = std::min(scale, max_height_dip / screen_size_dip.height()); | 412 scale = std::min(scale, max_height_dip / screen_size_dip.height()); |
406 } | 413 } |
407 | 414 |
408 if (scale <= 0) | 415 if (scale <= 0) |
409 scale = 0.1; | 416 scale = 0.1; |
410 | 417 |
411 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( | 418 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( |
412 gfx::ScaleSize(viewport_size_dip, scale))); | 419 gfx::ScaleSize(viewport_size_dip, scale))); |
413 | 420 |
414 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { | 421 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { |
415 processing_screencast_frame_ = true; | |
416 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); | 422 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); |
417 view->CopyFromCompositingSurface( | 423 view->CopyFromCompositingSurface( |
418 viewport_bounds_dip, | 424 viewport_bounds_dip, |
419 snapshot_size_dip, | 425 snapshot_size_dip, |
420 base::Bind(&PageHandler::ScreencastFrameCaptured, | 426 base::Bind(&PageHandler::ScreencastFrameCaptured, |
421 weak_factory_.GetWeakPtr(), | 427 weak_factory_.GetWeakPtr(), |
422 last_compositor_frame_metadata_), | 428 last_compositor_frame_metadata_, |
429 ++screencast_frame_sent_), | |
423 kN32_SkColorType); | 430 kN32_SkColorType); |
424 } | 431 } |
425 } | 432 } |
426 | 433 |
427 void PageHandler::ScreencastFrameCaptured( | 434 void PageHandler::ScreencastFrameCaptured( |
428 const cc::CompositorFrameMetadata& metadata, | 435 const cc::CompositorFrameMetadata& metadata, |
436 int frame_number, | |
429 const SkBitmap& bitmap, | 437 const SkBitmap& bitmap, |
430 ReadbackResponse response) { | 438 ReadbackResponse response) { |
431 if (response != READBACK_SUCCESS) { | 439 if (response != READBACK_SUCCESS) { |
432 processing_screencast_frame_ = false; | |
433 if (capture_retry_count_) { | 440 if (capture_retry_count_) { |
434 --capture_retry_count_; | 441 --capture_retry_count_; |
435 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 442 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
436 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, | 443 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, |
437 weak_factory_.GetWeakPtr()), | 444 weak_factory_.GetWeakPtr()), |
438 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); | 445 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); |
439 } | 446 } |
447 --screencast_frame_sent_; | |
dgozman
2015/11/20 22:53:23
This violates the assumption of increasing screenc
pfeldman
2015/11/20 23:18:25
Not really.
| |
440 return; | 448 return; |
441 } | 449 } |
442 base::PostTaskAndReplyWithResult( | 450 base::PostTaskAndReplyWithResult( |
443 base::WorkerPool::GetTaskRunner(true).get(), | 451 base::WorkerPool::GetTaskRunner(true).get(), |
444 FROM_HERE, | 452 FROM_HERE, |
445 base::Bind(&EncodeScreencastFrame, | 453 base::Bind(&EncodeScreencastFrame, |
446 bitmap, screencast_format_, screencast_quality_), | 454 bitmap, screencast_format_, screencast_quality_), |
447 base::Bind(&PageHandler::ScreencastFrameEncoded, | 455 base::Bind(&PageHandler::ScreencastFrameEncoded, |
448 weak_factory_.GetWeakPtr(), metadata, base::Time::Now())); | 456 weak_factory_.GetWeakPtr(), metadata, |
457 frame_number, base::Time::Now())); | |
449 } | 458 } |
450 | 459 |
451 void PageHandler::ScreencastFrameEncoded( | 460 void PageHandler::ScreencastFrameEncoded( |
452 const cc::CompositorFrameMetadata& metadata, | 461 const cc::CompositorFrameMetadata& metadata, |
462 int frame_number, | |
453 const base::Time& timestamp, | 463 const base::Time& timestamp, |
454 const std::string& data) { | 464 const std::string& data) { |
455 processing_screencast_frame_ = false; | |
456 | |
457 // Consider metadata empty in case it has no device scale factor. | 465 // Consider metadata empty in case it has no device scale factor. |
458 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) | 466 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { |
467 --screencast_frame_sent_; | |
459 return; | 468 return; |
469 } | |
460 | 470 |
461 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 471 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
462 host_->GetView()); | 472 host_->GetView()); |
463 if (!view) | 473 if (!view) { |
474 --screencast_frame_sent_; | |
464 return; | 475 return; |
476 } | |
465 | 477 |
466 gfx::SizeF screen_size_dip = | 478 gfx::SizeF screen_size_dip = |
467 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), | 479 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), |
468 1 / metadata.device_scale_factor); | 480 1 / metadata.device_scale_factor); |
469 scoped_refptr<ScreencastFrameMetadata> param_metadata = | 481 scoped_refptr<ScreencastFrameMetadata> param_metadata = |
470 ScreencastFrameMetadata::Create() | 482 ScreencastFrameMetadata::Create() |
471 ->set_page_scale_factor(metadata.page_scale_factor) | 483 ->set_page_scale_factor(metadata.page_scale_factor) |
472 ->set_offset_top(metadata.location_bar_content_translation.y()) | 484 ->set_offset_top(metadata.location_bar_content_translation.y()) |
473 ->set_device_width(screen_size_dip.width()) | 485 ->set_device_width(screen_size_dip.width()) |
474 ->set_device_height(screen_size_dip.height()) | 486 ->set_device_height(screen_size_dip.height()) |
475 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) | 487 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) |
476 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) | 488 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) |
477 ->set_timestamp(timestamp.ToDoubleT()); | 489 ->set_timestamp(timestamp.ToDoubleT()); |
478 client_->ScreencastFrame(ScreencastFrameParams::Create() | 490 client_->ScreencastFrame(ScreencastFrameParams::Create() |
479 ->set_data(data) | 491 ->set_data(data) |
480 ->set_metadata(param_metadata) | 492 ->set_metadata(param_metadata) |
481 ->set_frame_number(++screencast_frame_sent_)); | 493 ->set_frame_number(frame_number)); |
482 } | 494 } |
483 | 495 |
484 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, | 496 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, |
485 const unsigned char* png_data, | 497 const unsigned char* png_data, |
486 size_t png_size) { | 498 size_t png_size) { |
487 if (!png_data || !png_size) { | 499 if (!png_data || !png_size) { |
488 client_->SendError(command_id, | 500 client_->SendError(command_id, |
489 Response::InternalError("Unable to capture screenshot")); | 501 Response::InternalError("Unable to capture screenshot")); |
490 return; | 502 return; |
491 } | 503 } |
492 | 504 |
493 std::string base_64_data; | 505 std::string base_64_data; |
494 base::Base64Encode( | 506 base::Base64Encode( |
495 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), | 507 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), |
496 &base_64_data); | 508 &base_64_data); |
497 | 509 |
498 client_->SendCaptureScreenshotResponse(command_id, | 510 client_->SendCaptureScreenshotResponse(command_id, |
499 CaptureScreenshotResponse::Create()->set_data(base_64_data)); | 511 CaptureScreenshotResponse::Create()->set_data(base_64_data)); |
500 } | 512 } |
501 | 513 |
502 void PageHandler::OnColorPicked(int r, int g, int b, int a) { | 514 void PageHandler::OnColorPicked(int r, int g, int b, int a) { |
503 scoped_refptr<dom::RGBA> color = | 515 scoped_refptr<dom::RGBA> color = |
504 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); | 516 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); |
505 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); | 517 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); |
506 } | 518 } |
507 | 519 |
508 } // namespace page | 520 } // namespace page |
509 } // namespace devtools | 521 } // namespace devtools |
510 } // namespace content | 522 } // namespace content |
OLD | NEW |