// Copyright (c) 2015 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. #include "atom/browser/api/frame_subscriber.h" #include "atom/common/node_includes.h" #include "base/bind.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" namespace atom { namespace api { FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback) : isolate_(isolate), size_(size), callback_(callback), weak_factory_(this) { } bool FrameSubscriber::ShouldCaptureFrame( const gfx::Rect& damage_rect, base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { *storage = media::VideoFrame::CreateFrame( media::PIXEL_FORMAT_YV12, size_, gfx::Rect(size_), size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, weak_factory_.GetWeakPtr(), *storage); return true; } void FrameSubscriber::OnFrameDelivered( scoped_refptr frame, base::TimeTicks, bool result) { if (!result) 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; 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); callback_.Run(buffer.ToLocalChecked()); } } // namespace api } // namespace atom