Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(996)

Side by Side Diff: content/renderer/media/image_capture_frame_grabber.cc

Issue 1899403002: MediaStream Image Capture (2): Platform::ImageCaptureFrameGrabber and grabFrame() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. LayoutTests: Replace assert_array_equals with an for-each: assert_aprox_equals Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/image_capture_frame_grabber.h"
6
7 #include "media/base/bind_to_current_loop.h"
8 #include "media/base/video_frame.h"
9 #include "media/base/video_util.h"
10 #include "skia/ext/platform_canvas.h"
11 #include "third_party/WebKit/public/platform/WebCallbacks.h"
12 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
13 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
14 #include "third_party/libyuv/include/libyuv.h"
15 #include "third_party/skia/include/core/SkImage.h"
16 #include "third_party/skia/include/core/SkSurface.h"
17
18 namespace content {
19
20 using blink::WebImageCaptureGrabFrameCallbacks;
21
22 namespace {
23
24 void OnError(std::unique_ptr<WebImageCaptureGrabFrameCallbacks> callbacks) {
25 callbacks->onError();
26 }
27
28 // This internal method receives a |frame| and converts its pixels into a
29 // SkImage via an internal SkSurface and SkPixmap. Alpha channel, if any, is
30 // copied.
31 void OnVideoFrame(const ImageCaptureFrameGrabber::SkImageDeliverCB& callback,
32 const scoped_refptr<media::VideoFrame>& frame,
33 base::TimeTicks /* current_time */) {
34 DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 ||
35 frame->format() == media::PIXEL_FORMAT_I420 ||
36 frame->format() == media::PIXEL_FORMAT_YV12A);
37
38 const SkAlphaType alpha = media::IsOpaque(frame->format())
39 ? kOpaque_SkAlphaType
40 : kPremul_SkAlphaType;
41 const SkImageInfo info = SkImageInfo::MakeN32(
42 frame->visible_rect().width(), frame->visible_rect().height(), alpha);
43
44 sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
45 DCHECK(surface);
46
47 SkPixmap pixmap;
48 if (!skia::GetWritablePixels(surface->getCanvas(), &pixmap)) {
49 DLOG(ERROR) << "Error trying to map SkSurface's pixels";
50 callback.Run(sk_sp<SkImage>());
51 return;
52 }
53
54 libyuv::I420ToARGB(frame->visible_data(media::VideoFrame::kYPlane),
55 frame->stride(media::VideoFrame::kYPlane),
56 frame->visible_data(media::VideoFrame::kUPlane),
57 frame->stride(media::VideoFrame::kUPlane),
58 frame->visible_data(media::VideoFrame::kVPlane),
59 frame->stride(media::VideoFrame::kVPlane),
60 static_cast<uint8*>(pixmap.writable_addr()),
61 pixmap.width() * 4, pixmap.width(), pixmap.height());
62
63 if (frame->format() == media::PIXEL_FORMAT_YV12A) {
64 DCHECK(!info.isOpaque());
65 // This function copies any plane into the alpha channel of an ARGB image.
66 libyuv::ARGBCopyYToAlpha(frame->visible_data(media::VideoFrame::kAPlane),
67 frame->stride(media::VideoFrame::kAPlane),
68 static_cast<uint8*>(pixmap.writable_addr()),
69 pixmap.width() * 4, pixmap.width(),
70 pixmap.height());
71 }
72
73 callback.Run(surface->makeImageSnapshot());
74 }
75
76 } // anonymous namespace
77
78 ImageCaptureFrameGrabber::ImageCaptureFrameGrabber() : weak_factory_(this) {}
79
80 ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() {
81 DCHECK(thread_checker_.CalledOnValidThread());
82 }
83
84 void ImageCaptureFrameGrabber::grabFrame(
85 blink::WebMediaStreamTrack* track,
86 WebImageCaptureGrabFrameCallbacks* callbacks) {
87 DVLOG(1) << __FUNCTION__;
88 DCHECK(thread_checker_.CalledOnValidThread());
89 DCHECK(!!callbacks);
90
91 DCHECK(track && !track->isNull() && track->getExtraData());
92 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track->source().getType());
93
94 ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks =
95 make_scoped_web_callbacks(callbacks, base::Bind(&OnError));
96
97 // ConnectToTrack() must happen on render's Main Thread, whereas VideoFrames
98 // are delivered on a background thread though, so we Bind the callback to our
99 // current thread.
100 MediaStreamVideoSink::ConnectToTrack(
101 *track,
102 base::Bind(&OnVideoFrame, media::BindToCurrentLoop(base::Bind(
103 &ImageCaptureFrameGrabber::OnSkImage,
104 weak_factory_.GetWeakPtr(),
105 base::Passed(&scoped_callbacks)))));
106 }
107
108 void ImageCaptureFrameGrabber::OnSkImage(
109 ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> callbacks,
110 sk_sp<SkImage> image) {
111 DVLOG(1) << __FUNCTION__;
112 DCHECK(thread_checker_.CalledOnValidThread());
113
114 MediaStreamVideoSink::DisconnectFromTrack();
115 if (image)
116 callbacks.PassCallbacks()->onSuccess(image);
117 else
118 callbacks.PassCallbacks()->onError();
119 }
120
121 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698