Index: content/renderer/media/image_capture_frame_grabber.cc |
diff --git a/content/renderer/media/image_capture_frame_grabber.cc b/content/renderer/media/image_capture_frame_grabber.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e0f2d3e660437ef02a82cfffdee2d2926f1a1ac5 |
--- /dev/null |
+++ b/content/renderer/media/image_capture_frame_grabber.cc |
@@ -0,0 +1,98 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/renderer/media/image_capture_frame_grabber.h" |
+ |
+#include "media/base/bind_to_current_loop.h" |
+#include "media/base/video_frame.h" |
+#include "media/base/video_util.h" |
+#include "third_party/WebKit/public/platform/WebCallbacks.h" |
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
+#include "third_party/libyuv/include/libyuv.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+ |
+namespace content { |
+ |
+using blink::WebImageCaptureGrabFrameCallbacks; |
+ |
+namespace { |
+ |
+void OnError(std::unique_ptr<WebImageCaptureGrabFrameCallbacks> callbacks) { |
+ callbacks->onError(); |
+} |
+ |
+void OnVideoFrame(const ImageCaptureFrameGrabber::SkBitmapDeliverCB& callback, |
+ const scoped_refptr<media::VideoFrame>& video_frame, |
+ base::TimeTicks /* current_time */) { |
+ DCHECK(video_frame->format() == media::PIXEL_FORMAT_YV12 || |
+ video_frame->format() == media::PIXEL_FORMAT_I420 || |
+ video_frame->format() == media::PIXEL_FORMAT_YV12A); |
+ |
+ scoped_refptr<media::VideoFrame> frame = video_frame; |
+ // Drop alpha channel since it's not supported in libyuv conversion to RGBA. |
+ if (frame->format() == media::PIXEL_FORMAT_YV12A) |
+ frame = media::WrapAsI420VideoFrame(video_frame); |
+ |
+ std::unique_ptr<SkBitmap> bitmap(new SkBitmap()); |
+ bitmap->allocN32Pixels(frame->visible_rect().width(), |
+ frame->visible_rect().height(), |
+ true /* isOpaque */); |
+ |
+ libyuv::I420ToARGB(frame->visible_data(media::VideoFrame::kYPlane), |
+ frame->stride(media::VideoFrame::kYPlane), |
+ frame->visible_data(media::VideoFrame::kUPlane), |
+ frame->stride(media::VideoFrame::kUPlane), |
+ frame->visible_data(media::VideoFrame::kVPlane), |
+ frame->stride(media::VideoFrame::kVPlane), |
+ static_cast<uint8*>(bitmap->getPixels()), |
+ bitmap->width() * 4, bitmap->width(), bitmap->height()); |
+ bitmap->setImmutable(); |
+ |
+ callback.Run(std::move(bitmap)); |
+} |
+ |
+} // anonymous namespace |
+ |
+ImageCaptureFrameGrabber::ImageCaptureFrameGrabber() : weak_factory_(this) {} |
+ |
+ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+} |
+ |
+void ImageCaptureFrameGrabber::grabFrame( |
+ blink::WebMediaStreamTrack* track, |
+ WebImageCaptureGrabFrameCallbacks* callbacks) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(!!callbacks); |
+ |
+ DCHECK(track && !track->isNull() && track->getExtraData()); |
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track->source().getType()); |
+ |
+ ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks = |
+ make_scoped_web_callbacks(callbacks, base::Bind(&OnError)); |
+ |
+ // ConnectToTrack() must happen on render's Main Thread, whereas VideoFrames |
+ // are delivered on a background thread though, so we Bind the callback to our |
+ // current thread. |
+ MediaStreamVideoSink::ConnectToTrack( |
+ *track, |
+ base::Bind(&OnVideoFrame, media::BindToCurrentLoop(base::Bind( |
+ &ImageCaptureFrameGrabber::OnSkBitmap, |
+ weak_factory_.GetWeakPtr(), |
+ base::Passed(&scoped_callbacks))))); |
+} |
+ |
+void ImageCaptureFrameGrabber::OnSkBitmap( |
+ ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> callbacks, |
+ std::unique_ptr<SkBitmap> bitmap) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ MediaStreamVideoSink::DisconnectFromTrack(); |
+ callbacks.PassCallbacks()->onSuccess(std::move(bitmap)); |
+} |
+ |
+} // namespace content |