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

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

Issue 1467103003: Basic use implementation for MediaStream from Canvas: captureStream() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 2015 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/canvas_capture_handler.h"
6
7 #include "base/bind_helpers.h"
8 #include "content/public/renderer/media_stream_api.h"
9 #include "content/public/renderer/render_thread.h"
10 #include "content/renderer/render_thread_impl.h"
11 #include "third_party/libyuv/include/libyuv.h"
12
13 namespace {
14 const float kDefaultFrameRate = 60.0f;
15 } // anonymous namespace
16
17 namespace content {
18
19 class CanvasCaptureHandler::VideoCapturerSource
20 : public media::VideoCapturerSource {
21 public:
22 explicit VideoCapturerSource(CanvasCaptureHandler* canvas_handler)
23 : canvas_handler_(canvas_handler) {}
24 protected:
25 void GetCurrentSupportedFormats(
26 int max_requested_width,
27 int max_requested_height,
28 double max_requested_frame_rate,
29 const VideoCaptureDeviceFormatsCB& callback) override;
30 void StartCapture(const media::VideoCaptureParams& params,
31 const VideoCaptureDeliverFrameCB& frame_callback,
32 const RunningCallback& running_callback) override {
33 canvas_handler_->StartVideoCapture(params, frame_callback,
34 running_callback);
35 }
36 void StopCapture() override { canvas_handler_->StopVideoCapture(); }
37
38 private:
39 // CanvasCaptureHandler is owned by blink and guaranteed to be alive during
40 // the lifetime of this class.
41 CanvasCaptureHandler* canvas_handler_;
42 };
43
44 void CanvasCaptureHandler::VideoCapturerSource::GetCurrentSupportedFormats(
45 int max_requested_width,
46 int max_requested_height,
47 double max_requested_frame_rate,
48 const VideoCaptureDeviceFormatsCB& callback) {
49 const blink::WebSize& size = canvas_handler_->GetSourceSize();
50 const media::VideoCaptureFormat format(gfx::Size(size.width, size.height),
51 kDefaultFrameRate,
52 media::PIXEL_FORMAT_I420);
53 media::VideoCaptureFormats formats;
54 formats.push_back(format);
55 callback.Run(formats);
56 }
57
58 class CanvasCaptureHandler::CanvasCaptureHandlerDelegate {
59 public:
60 explicit CanvasCaptureHandlerDelegate(
61 media::VideoCapturerSource::VideoCaptureDeliverFrameCB new_frame_callback)
62 : new_frame_callback_(new_frame_callback),
63 io_task_runner_(content::RenderThread::Get()->GetIOMessageLoopProxy()) {
64 }
65
66 void sendNewFrameOnIOThread(
67 const scoped_refptr<media::VideoFrame>& video_frame,
68 const base::TimeTicks& current_time) {
69 DCHECK(io_task_runner_->BelongsToCurrentThread());
70 new_frame_callback_.Run(video_frame, current_time);
71 }
72
73 private:
74 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB
75 new_frame_callback_;
76 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
77 DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerDelegate);
78 };
79
80 CanvasCaptureHandler::CanvasCaptureHandler(const blink::WebSize& size,
81 blink::WebMediaStream* stream)
82 : ask_for_new_frame_(false),
83 size_(size),
84 io_task_runner_(content::RenderThread::Get()->GetIOMessageLoopProxy()) {
85 scoped_ptr<media::VideoCapturerSource> video(
86 new CanvasCaptureHandler::VideoCapturerSource(this));
87 content::AddVideoTrackToMediaStream(video.Pass(), false, false, stream);
88 }
89
90 CanvasCaptureHandler::~CanvasCaptureHandler() {
91 DVLOG(3) << __FUNCTION__;
92 DCHECK(thread_checker_.CalledOnValidThread());
93 }
94
95 void CanvasCaptureHandler::sendNewFrame(const blink::WebSkImage& image) {
96 createNewFrame(image);
97 }
98
99 bool CanvasCaptureHandler::needsNewFrameCapture() const {
100 return ask_for_new_frame_;
101 }
102
103 void CanvasCaptureHandler::StartVideoCapture(
104 const media::VideoCaptureParams& params,
105 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB&
106 new_frame_callback,
107 const media::VideoCapturerSource::RunningCallback& running_callback) {
108 DVLOG(3) << __FUNCTION__ << " requested "
109 << media::VideoCaptureFormat::ToString(params.requested_format);
110 DCHECK(params.requested_format.IsValid());
111 DCHECK(thread_checker_.CalledOnValidThread());
112
113 // TODO(emircan): Accomodate to the given frame rate constraints here.
114 capture_format_ = params.requested_format;
115 ask_for_new_frame_ = true;
116
117 delegate_ =
118 make_scoped_ptr(new CanvasCaptureHandlerDelegate(new_frame_callback));
119 DCHECK(delegate_);
120 running_callback.Run(true);
121 }
122
123 void CanvasCaptureHandler::StopVideoCapture() {
124 DVLOG(3) << __FUNCTION__;
125 DCHECK(thread_checker_.CalledOnValidThread());
126 ask_for_new_frame_ = false;
127 delegate_.reset();
128 }
129
130 void CanvasCaptureHandler::createNewFrame(const blink::WebSkImage& image) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132
133 DCHECK(!image.isNull());
134 const gfx::Size size(image.width(), image.height());
135 if (size != last_size) {
136 temp_data_.resize(
137 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_ARGB, size));
138 row_bytes_ = media::VideoFrame::RowBytes(
139 0, media::PIXEL_FORMAT_ARGB, capture_format_.frame_size.width());
140 image_info_ =
141 SkImageInfo::Make(size.width(), size.height(),
142 kBGRA_8888_SkColorType, kPremul_SkAlphaType);
143 last_size = size;
144 }
145
146 image.readPixels(image_info_, &temp_data_[0], row_bytes_, 0, 0);
147 scoped_refptr<media::VideoFrame> video_frame =
148 frame_pool_.CreateFrame(media::PIXEL_FORMAT_I420, size, gfx::Rect(size),
149 size, base::TimeTicks::Now() - base::TimeTicks());
150 libyuv::ARGBToI420(temp_data_.data(), row_bytes_,
151 video_frame->data(media::VideoFrame::kYPlane),
152 video_frame->stride(media::VideoFrame::kYPlane),
153 video_frame->data(media::VideoFrame::kUPlane),
154 video_frame->stride(media::VideoFrame::kUPlane),
155 video_frame->data(media::VideoFrame::kVPlane),
156 video_frame->stride(media::VideoFrame::kVPlane),
157 size.width(), size.height());
158
159 if (!delegate_)
160 return;
161 io_task_runner_->PostTask(
162 FROM_HERE,
163 base::Bind(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
164 sendNewFrameOnIOThread,
165 base::Unretained(delegate_.get()), video_frame,
166 base::TimeTicks()));
167 }
168
169 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698