From 7bf17f2541680835fa60f9666becb6224061ae41 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 18 Feb 2016 01:15:00 +0100 Subject: [PATCH] Improved frame subscriber - now we only use framesubscription events as an event, and we copy from the backing store directly (instead of accessing it through a videoframe) --- atom/browser/api/atom_api_web_contents.cc | 2 +- atom/browser/api/frame_subscriber.cc | 63 ++++++++++++++--------- atom/browser/api/frame_subscriber.h | 10 ++-- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b04553e654b8..6531874e6a98 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1065,7 +1065,7 @@ void WebContents::BeginFrameSubscription( const auto view = web_contents()->GetRenderWidgetHostView(); if (view) { FrameSubscriber* frame_subscriber = new FrameSubscriber( - isolate(), view->GetVisibleViewportSize(), callback); + isolate(), view, callback); scoped_ptr del_frame_subscriber( frame_subscriber->GetSubscriber()); view->BeginFrameSubscription(del_frame_subscriber.Pass()); diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 7d973892405c..60bf84c0eb94 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -8,6 +8,8 @@ #include "base/bind.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" +#include "content/public/browser/render_widget_host.h" +#include "ui/gfx/screen.h" namespace atom { @@ -16,10 +18,11 @@ namespace api { using Subscriber = FrameSubscriber::Subscriber; FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, - const gfx::Size& size, + content::RenderWidgetHostView* view, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback), pending_frames(0) { + : isolate_(isolate), callback_(callback), pending_frames(0), view_(view) { subscriber_ = new Subscriber(this); + size_ = view->GetVisibleViewportSize(); } Subscriber::Subscriber( @@ -36,14 +39,32 @@ bool Subscriber::ShouldCaptureFrame( base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { - *storage = media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, - frame_subscriber_->size_, gfx::Rect(frame_subscriber_->size_), - frame_subscriber_->size_, base::TimeDelta()); - *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(frame_subscriber_), *storage); + const auto view = frame_subscriber_->view_; + const auto host = view ? view->GetRenderWidgetHost() : nullptr; + if (!view || !host) { + return false; + } + + const gfx::Size view_size = view->GetViewBounds().size(); + + gfx::Size bitmap_size = view_size; + const gfx::NativeView native_view = view->GetNativeView(); + gfx::Screen* const screen = gfx::Screen::GetScreenFor(native_view); + const float scale = + screen->GetDisplayNearestWindow(native_view).device_scale_factor(); + if (scale > 1.0f) + bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); + + host->CopyFromBackingStore( + gfx::Rect(view_size), + bitmap_size, + base::Bind(&FrameSubscriber::OnFrameDelivered, + base::Unretained(frame_subscriber_), + frame_subscriber_->callback_), + kBGRA_8888_SkColorType); + frame_subscriber_->pending_frames++; - return true; + return false; } Subscriber* FrameSubscriber::GetSubscriber() { @@ -60,33 +81,25 @@ bool FrameSubscriber::RequestDestruct() { return deletable; } -void FrameSubscriber::OnFrameDelivered( - scoped_refptr frame, base::TimeTicks, bool result) { +void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback, + const SkBitmap& bitmap, content::ReadbackResponse response){ pending_frames--; - if (RequestDestruct() || subscriber_ == NULL || !result) + if (RequestDestruct() || subscriber_ == NULL || bitmap.computeSize64() == 0) return; v8::Locker locker(isolate_); v8::HandleScope handle_scope(isolate_); - gfx::Rect rect = frame->visible_rect(); - size_t rgb_arr_size = rect.width() * rect.height() * 4; + size_t rgb_arr_size = bitmap.width() * bitmap.height() * + bitmap.bytesPerPixel(); v8::MaybeLocal buffer = node::Buffer::New(isolate_, rgb_arr_size); if (buffer.IsEmpty()) return; - // Convert a frame of YUV to 32 bit ARGB. - media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane), - frame->data(media::VideoFrame::kUPlane), - frame->data(media::VideoFrame::kVPlane), - reinterpret_cast( - node::Buffer::Data(buffer.ToLocalChecked())), - rect.width(), rect.height(), - frame->stride(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kUVPlane), - rect.width() * 4, - media::YV12); + bitmap.copyPixelsTo( + reinterpret_cast(node::Buffer::Data(buffer.ToLocalChecked())), + rgb_arr_size); callback_.Run(buffer.ToLocalChecked()); } diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index 6f6d66b6be80..745cf382adb6 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -6,7 +6,10 @@ #define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ #include "base/callback.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view_frame_subscriber.h" +#include "content/public/browser/readback_types.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" #include "v8/include/v8.h" @@ -35,19 +38,20 @@ class FrameSubscriber { }; FrameSubscriber(v8::Isolate* isolate, - const gfx::Size& size, + content::RenderWidgetHostView* view, const FrameCaptureCallback& callback); Subscriber* GetSubscriber(); private: - void OnFrameDelivered( - scoped_refptr frame, base::TimeTicks, bool); + void OnFrameDelivered(const FrameCaptureCallback& callback, + const SkBitmap& bitmap, content::ReadbackResponse response); bool RequestDestruct(); v8::Isolate* isolate_; gfx::Size size_; + content::RenderWidgetHostView* view_; FrameCaptureCallback callback_; Subscriber* subscriber_; int pending_frames;