frame_subscriber.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/api/frame_subscriber.h"
  5. #include "atom/common/native_mate_converters/gfx_converter.h"
  6. #include "base/bind.h"
  7. #include "content/public/browser/render_widget_host.h"
  8. #include "ui/display/display.h"
  9. #include "ui/display/screen.h"
  10. #include "atom/common/node_includes.h"
  11. namespace atom {
  12. namespace api {
  13. FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
  14. content::RenderWidgetHostView* view,
  15. const FrameCaptureCallback& callback,
  16. bool only_dirty)
  17. : isolate_(isolate),
  18. view_(view),
  19. callback_(callback),
  20. only_dirty_(only_dirty),
  21. source_id_for_copy_request_(base::UnguessableToken::Create()),
  22. weak_factory_(this) {}
  23. FrameSubscriber::~FrameSubscriber() = default;
  24. bool FrameSubscriber::ShouldCaptureFrame(
  25. const gfx::Rect& dirty_rect,
  26. base::TimeTicks present_time,
  27. scoped_refptr<media::VideoFrame>* storage,
  28. DeliverFrameCallback* callback) {
  29. if (!view_)
  30. return false;
  31. if (dirty_rect.IsEmpty())
  32. return false;
  33. gfx::Rect rect = gfx::Rect(view_->GetVisibleViewportSize());
  34. if (only_dirty_)
  35. rect = dirty_rect;
  36. gfx::Size view_size = rect.size();
  37. gfx::Size bitmap_size = view_size;
  38. gfx::NativeView native_view = view_->GetNativeView();
  39. const float scale = display::Screen::GetScreen()
  40. ->GetDisplayNearestView(native_view)
  41. .device_scale_factor();
  42. if (scale > 1.0f)
  43. bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
  44. rect = gfx::Rect(rect.origin(), bitmap_size);
  45. view_->CopyFromSurface(
  46. rect, rect.size(),
  47. base::Bind(&FrameSubscriber::OnFrameDelivered, weak_factory_.GetWeakPtr(),
  48. callback_, rect),
  49. kBGRA_8888_SkColorType);
  50. return false;
  51. }
  52. const base::UnguessableToken& FrameSubscriber::GetSourceIdForCopyRequest() {
  53. return source_id_for_copy_request_;
  54. }
  55. void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
  56. const gfx::Rect& damage_rect,
  57. const SkBitmap& bitmap,
  58. content::ReadbackResponse response) {
  59. if (response != content::ReadbackResponse::READBACK_SUCCESS)
  60. return;
  61. v8::Locker locker(isolate_);
  62. v8::HandleScope handle_scope(isolate_);
  63. size_t rgb_row_size = bitmap.width() * bitmap.bytesPerPixel();
  64. v8::MaybeLocal<v8::Object> buffer =
  65. node::Buffer::New(isolate_, rgb_row_size * bitmap.height());
  66. if (buffer.IsEmpty())
  67. return;
  68. auto local_buffer = buffer.ToLocalChecked();
  69. {
  70. auto* source = static_cast<const unsigned char*>(bitmap.getPixels());
  71. auto* target = node::Buffer::Data(local_buffer);
  72. for (int y = 0; y < bitmap.height(); ++y) {
  73. memcpy(target, source, rgb_row_size);
  74. source += bitmap.rowBytes();
  75. target += rgb_row_size;
  76. }
  77. }
  78. v8::Local<v8::Value> damage =
  79. mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
  80. callback_.Run(local_buffer, damage);
  81. }
  82. } // namespace api
  83. } // namespace atom