OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/canvas_capture_handler.h" | 5 #include "content/renderer/media/canvas_capture_handler.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 double frame_rate) | 31 double frame_rate) |
32 : frame_rate_(frame_rate), | 32 : frame_rate_(frame_rate), |
33 canvas_handler_(canvas_handler) {} | 33 canvas_handler_(canvas_handler) {} |
34 | 34 |
35 protected: | 35 protected: |
36 void GetCurrentSupportedFormats( | 36 void GetCurrentSupportedFormats( |
37 int max_requested_width, | 37 int max_requested_width, |
38 int max_requested_height, | 38 int max_requested_height, |
39 double max_requested_frame_rate, | 39 double max_requested_frame_rate, |
40 const VideoCaptureDeviceFormatsCB& callback) override { | 40 const VideoCaptureDeviceFormatsCB& callback) override { |
| 41 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
41 const blink::WebSize& size = canvas_handler_->GetSourceSize(); | 42 const blink::WebSize& size = canvas_handler_->GetSourceSize(); |
42 media::VideoCaptureFormats formats; | 43 media::VideoCaptureFormats formats; |
43 formats.push_back( | 44 formats.push_back( |
44 media::VideoCaptureFormat(gfx::Size(size.width, size.height), | 45 media::VideoCaptureFormat(gfx::Size(size.width, size.height), |
45 frame_rate_, media::PIXEL_FORMAT_I420)); | 46 frame_rate_, media::PIXEL_FORMAT_I420)); |
46 formats.push_back( | 47 formats.push_back( |
47 media::VideoCaptureFormat(gfx::Size(size.width, size.height), | 48 media::VideoCaptureFormat(gfx::Size(size.width, size.height), |
48 frame_rate_, media::PIXEL_FORMAT_YV12A)); | 49 frame_rate_, media::PIXEL_FORMAT_YV12A)); |
49 callback.Run(formats); | 50 callback.Run(formats); |
50 } | 51 } |
51 void StartCapture(const media::VideoCaptureParams& params, | 52 void StartCapture(const media::VideoCaptureParams& params, |
52 const VideoCaptureDeliverFrameCB& frame_callback, | 53 const VideoCaptureDeliverFrameCB& frame_callback, |
53 const RunningCallback& running_callback) override { | 54 const RunningCallback& running_callback) override { |
| 55 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
54 canvas_handler_->StartVideoCapture(params, frame_callback, | 56 canvas_handler_->StartVideoCapture(params, frame_callback, |
55 running_callback); | 57 running_callback); |
56 } | 58 } |
57 void StopCapture() override { | 59 void StopCapture() override { |
| 60 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
58 canvas_handler_->StopVideoCapture(); | 61 canvas_handler_->StopVideoCapture(); |
59 } | 62 } |
60 | 63 |
61 private: | 64 private: |
62 double frame_rate_; | 65 double frame_rate_; |
| 66 // Bound to Main Render thread. |
| 67 base::ThreadChecker main_render_thread_checker_; |
63 // CanvasCaptureHandler is owned by CanvasDrawListener in blink and | 68 // CanvasCaptureHandler is owned by CanvasDrawListener in blink and |
64 // guaranteed to be alive during the lifetime of this class. | 69 // guaranteed to be alive during the lifetime of this class. |
65 base::WeakPtr<CanvasCaptureHandler> canvas_handler_; | 70 base::WeakPtr<CanvasCaptureHandler> canvas_handler_; |
66 }; | 71 }; |
67 | 72 |
68 class CanvasCaptureHandler::CanvasCaptureHandlerDelegate { | 73 class CanvasCaptureHandler::CanvasCaptureHandlerDelegate { |
69 public: | 74 public: |
70 explicit CanvasCaptureHandlerDelegate( | 75 explicit CanvasCaptureHandlerDelegate( |
71 media::VideoCapturerSource::VideoCaptureDeliverFrameCB new_frame_callback) | 76 media::VideoCapturerSource::VideoCaptureDeliverFrameCB new_frame_callback) |
72 : new_frame_callback_(new_frame_callback), | 77 : new_frame_callback_(new_frame_callback), |
73 weak_ptr_factory_(this) { | 78 weak_ptr_factory_(this) { |
74 thread_checker_.DetachFromThread(); | 79 io_thread_checker_.DetachFromThread(); |
75 } | 80 } |
76 ~CanvasCaptureHandlerDelegate() { | 81 ~CanvasCaptureHandlerDelegate() { |
77 DCHECK(thread_checker_.CalledOnValidThread()); | 82 DCHECK(io_thread_checker_.CalledOnValidThread()); |
78 } | 83 } |
79 | 84 |
80 void SendNewFrameOnIOThread( | 85 void SendNewFrameOnIOThread( |
81 const scoped_refptr<media::VideoFrame>& video_frame, | 86 const scoped_refptr<media::VideoFrame>& video_frame, |
82 const base::TimeTicks& current_time) { | 87 const base::TimeTicks& current_time) { |
83 DCHECK(thread_checker_.CalledOnValidThread()); | 88 DCHECK(io_thread_checker_.CalledOnValidThread()); |
84 new_frame_callback_.Run(video_frame, current_time); | 89 new_frame_callback_.Run(video_frame, current_time); |
85 } | 90 } |
86 | 91 |
87 base::WeakPtr<CanvasCaptureHandlerDelegate> GetWeakPtrForIOThread() { | 92 base::WeakPtr<CanvasCaptureHandlerDelegate> GetWeakPtrForIOThread() { |
88 return weak_ptr_factory_.GetWeakPtr(); | 93 return weak_ptr_factory_.GetWeakPtr(); |
89 } | 94 } |
90 | 95 |
91 private: | 96 private: |
92 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB | 97 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB |
93 new_frame_callback_; | 98 new_frame_callback_; |
94 base::ThreadChecker thread_checker_; | 99 // Bound to IO thread. |
| 100 base::ThreadChecker io_thread_checker_; |
95 base::WeakPtrFactory<CanvasCaptureHandlerDelegate> weak_ptr_factory_; | 101 base::WeakPtrFactory<CanvasCaptureHandlerDelegate> weak_ptr_factory_; |
96 | 102 |
97 DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerDelegate); | 103 DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerDelegate); |
98 }; | 104 }; |
99 | 105 |
100 CanvasCaptureHandler::CanvasCaptureHandler( | 106 CanvasCaptureHandler::CanvasCaptureHandler( |
101 const blink::WebSize& size, | 107 const blink::WebSize& size, |
102 double frame_rate, | 108 double frame_rate, |
103 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | 109 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, |
104 blink::WebMediaStreamTrack* track) | 110 blink::WebMediaStreamTrack* track) |
105 : ask_for_new_frame_(false), | 111 : ask_for_new_frame_(false), |
106 size_(size), | 112 size_(size), |
107 io_task_runner_(io_task_runner), | 113 io_task_runner_(io_task_runner), |
108 weak_ptr_factory_(this) { | 114 weak_ptr_factory_(this) { |
109 scoped_ptr<media::VideoCapturerSource> video_source( | 115 scoped_ptr<media::VideoCapturerSource> video_source( |
110 new CanvasCaptureHandler::VideoCapturerSource( | 116 new CanvasCaptureHandler::VideoCapturerSource( |
111 weak_ptr_factory_.GetWeakPtr(), frame_rate)); | 117 weak_ptr_factory_.GetWeakPtr(), frame_rate)); |
112 AddVideoCapturerSourceToVideoTrack(std::move(video_source), track); | 118 AddVideoCapturerSourceToVideoTrack(std::move(video_source), track); |
113 } | 119 } |
114 | 120 |
115 CanvasCaptureHandler::~CanvasCaptureHandler() { | 121 CanvasCaptureHandler::~CanvasCaptureHandler() { |
116 DVLOG(3) << __FUNCTION__; | 122 DVLOG(3) << __FUNCTION__; |
117 DCHECK(thread_checker_.CalledOnValidThread()); | 123 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
118 io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()); | 124 io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()); |
119 } | 125 } |
120 | 126 |
121 // static | 127 // static |
122 CanvasCaptureHandler* CanvasCaptureHandler::CreateCanvasCaptureHandler( | 128 CanvasCaptureHandler* CanvasCaptureHandler::CreateCanvasCaptureHandler( |
123 const blink::WebSize& size, | 129 const blink::WebSize& size, |
124 double frame_rate, | 130 double frame_rate, |
125 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | 131 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, |
126 blink::WebMediaStreamTrack* track) { | 132 blink::WebMediaStreamTrack* track) { |
127 // Save histogram data so we can see how much CanvasCapture is used. | 133 // Save histogram data so we can see how much CanvasCapture is used. |
128 // The histogram counts the number of calls to the JS API. | 134 // The histogram counts the number of calls to the JS API. |
129 UpdateWebRTCMethodCount(WEBKIT_CANVAS_CAPTURE_STREAM); | 135 UpdateWebRTCMethodCount(WEBKIT_CANVAS_CAPTURE_STREAM); |
130 | 136 |
131 return new CanvasCaptureHandler(size, frame_rate, io_task_runner, track); | 137 return new CanvasCaptureHandler(size, frame_rate, io_task_runner, track); |
132 } | 138 } |
133 | 139 |
134 void CanvasCaptureHandler::sendNewFrame(const SkImage* image) { | 140 void CanvasCaptureHandler::sendNewFrame(const SkImage* image) { |
135 DCHECK(thread_checker_.CalledOnValidThread()); | 141 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
136 CreateNewFrame(image); | 142 CreateNewFrame(image); |
137 } | 143 } |
138 | 144 |
139 bool CanvasCaptureHandler::needsNewFrame() const { | 145 bool CanvasCaptureHandler::needsNewFrame() const { |
140 DCHECK(thread_checker_.CalledOnValidThread()); | 146 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
141 return ask_for_new_frame_; | 147 return ask_for_new_frame_; |
142 } | 148 } |
143 | 149 |
144 void CanvasCaptureHandler::StartVideoCapture( | 150 void CanvasCaptureHandler::StartVideoCapture( |
145 const media::VideoCaptureParams& params, | 151 const media::VideoCaptureParams& params, |
146 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB& | 152 const media::VideoCapturerSource::VideoCaptureDeliverFrameCB& |
147 new_frame_callback, | 153 new_frame_callback, |
148 const media::VideoCapturerSource::RunningCallback& running_callback) { | 154 const media::VideoCapturerSource::RunningCallback& running_callback) { |
149 DVLOG(3) << __FUNCTION__ << " requested " | 155 DVLOG(3) << __FUNCTION__ << " requested " |
150 << media::VideoCaptureFormat::ToString(params.requested_format); | 156 << media::VideoCaptureFormat::ToString(params.requested_format); |
| 157 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
151 DCHECK(params.requested_format.IsValid()); | 158 DCHECK(params.requested_format.IsValid()); |
152 DCHECK(thread_checker_.CalledOnValidThread()); | |
153 | 159 |
154 // TODO(emircan): Accomodate to the given frame rate constraints here. | 160 // TODO(emircan): Accomodate to the given frame rate constraints here. |
155 capture_format_ = params.requested_format; | 161 capture_format_ = params.requested_format; |
156 delegate_.reset(new CanvasCaptureHandlerDelegate(new_frame_callback)); | 162 delegate_.reset(new CanvasCaptureHandlerDelegate(new_frame_callback)); |
157 DCHECK(delegate_); | 163 DCHECK(delegate_); |
158 ask_for_new_frame_ = true; | 164 ask_for_new_frame_ = true; |
159 running_callback.Run(true); | 165 running_callback.Run(true); |
160 } | 166 } |
161 | 167 |
162 void CanvasCaptureHandler::StopVideoCapture() { | 168 void CanvasCaptureHandler::StopVideoCapture() { |
163 DVLOG(3) << __FUNCTION__; | 169 DVLOG(3) << __FUNCTION__; |
164 DCHECK(thread_checker_.CalledOnValidThread()); | 170 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
165 ask_for_new_frame_ = false; | 171 ask_for_new_frame_ = false; |
166 io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()); | 172 io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()); |
167 } | 173 } |
168 | 174 |
169 void CanvasCaptureHandler::CreateNewFrame(const SkImage* image) { | 175 void CanvasCaptureHandler::CreateNewFrame(const SkImage* image) { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 176 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
171 DCHECK(image); | 177 DCHECK(image); |
172 | 178 |
173 const gfx::Size size(image->width(), image->height()); | 179 const gfx::Size size(image->width(), image->height()); |
174 if (size != last_size) { | 180 if (size != last_size) { |
175 temp_data_.resize( | 181 temp_data_.resize( |
176 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_ARGB, size)); | 182 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_ARGB, size)); |
177 row_bytes_ = | 183 row_bytes_ = |
178 media::VideoFrame::RowBytes(0, media::PIXEL_FORMAT_ARGB, size.width()); | 184 media::VideoFrame::RowBytes(0, media::PIXEL_FORMAT_ARGB, size.width()); |
179 image_info_ = | 185 image_info_ = |
180 SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType, | 186 SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType, |
(...skipping 25 matching lines...) Expand all Loading... |
206 if (!isOpaque) { | 212 if (!isOpaque) { |
207 for (int p = 0; p < size.GetArea(); ++p) | 213 for (int p = 0; p < size.GetArea(); ++p) |
208 video_frame->data(media::VideoFrame::kAPlane)[p] = temp_data_[p * 4 + 3]; | 214 video_frame->data(media::VideoFrame::kAPlane)[p] = temp_data_[p * 4 + 3]; |
209 } | 215 } |
210 | 216 |
211 io_task_runner_->PostTask( | 217 io_task_runner_->PostTask( |
212 FROM_HERE, | 218 FROM_HERE, |
213 base::Bind(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate:: | 219 base::Bind(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate:: |
214 SendNewFrameOnIOThread, | 220 SendNewFrameOnIOThread, |
215 delegate_->GetWeakPtrForIOThread(), video_frame, | 221 delegate_->GetWeakPtrForIOThread(), video_frame, |
216 base::TimeTicks())); | 222 base::TimeTicks::Now())); |
217 } | 223 } |
218 | 224 |
219 void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack( | 225 void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack( |
220 scoped_ptr<media::VideoCapturerSource> source, | 226 scoped_ptr<media::VideoCapturerSource> source, |
221 blink::WebMediaStreamTrack* web_track) { | 227 blink::WebMediaStreamTrack* web_track) { |
222 std::string str_track_id; | 228 std::string str_track_id; |
223 base::Base64Encode(base::RandBytesAsString(64), &str_track_id); | 229 base::Base64Encode(base::RandBytesAsString(64), &str_track_id); |
224 const blink::WebString track_id = base::UTF8ToUTF16(str_track_id); | 230 const blink::WebString track_id = base::UTF8ToUTF16(str_track_id); |
225 blink::WebMediaStreamSource webkit_source; | 231 blink::WebMediaStreamSource webkit_source; |
226 scoped_ptr<MediaStreamVideoSource> media_stream_source( | 232 scoped_ptr<MediaStreamVideoSource> media_stream_source( |
227 new MediaStreamVideoCapturerSource( | 233 new MediaStreamVideoCapturerSource( |
228 MediaStreamSource::SourceStoppedCallback(), std::move(source))); | 234 MediaStreamSource::SourceStoppedCallback(), std::move(source))); |
229 webkit_source.initialize(track_id, blink::WebMediaStreamSource::TypeVideo, | 235 webkit_source.initialize(track_id, blink::WebMediaStreamSource::TypeVideo, |
230 track_id, false, true); | 236 track_id, false, true); |
231 webkit_source.setExtraData(media_stream_source.get()); | 237 webkit_source.setExtraData(media_stream_source.get()); |
232 | 238 |
233 web_track->initialize(webkit_source); | 239 web_track->initialize(webkit_source); |
234 blink::WebMediaConstraints constraints; | 240 blink::WebMediaConstraints constraints; |
235 constraints.initialize(); | 241 constraints.initialize(); |
236 web_track->setExtraData(new MediaStreamVideoTrack( | 242 web_track->setExtraData(new MediaStreamVideoTrack( |
237 media_stream_source.release(), constraints, | 243 media_stream_source.release(), constraints, |
238 MediaStreamVideoSource::ConstraintsCallback(), true)); | 244 MediaStreamVideoSource::ConstraintsCallback(), true)); |
239 } | 245 } |
240 | 246 |
241 } // namespace content | 247 } // namespace content |
OLD | NEW |