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

Side by Side Diff: content/browser/media/capture/desktop_capture_device.cc

Issue 2050353002: Update webrtc::DesktopCapturer clients to implement OnCaptureResult(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/browser/media/capture/desktop_capture_device.h" 5 #include "content/browser/media/capture/desktop_capture_device.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <string.h> 9 #include <string.h>
10 #include <utility> 10 #include <utility>
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 DesktopMediaID::Type type); 68 DesktopMediaID::Type type);
69 ~Core() override; 69 ~Core() override;
70 70
71 // Implementation of VideoCaptureDevice methods. 71 // Implementation of VideoCaptureDevice methods.
72 void AllocateAndStart(const media::VideoCaptureParams& params, 72 void AllocateAndStart(const media::VideoCaptureParams& params,
73 std::unique_ptr<Client> client); 73 std::unique_ptr<Client> client);
74 74
75 void SetNotificationWindowId(gfx::NativeViewId window_id); 75 void SetNotificationWindowId(gfx::NativeViewId window_id);
76 76
77 private: 77 private:
78 78 // webrtc::DesktopCapturer::Callback interface.
79 // webrtc::DesktopCapturer::Callback interface 79 void OnCaptureResult(
80 void OnCaptureCompleted(webrtc::DesktopFrame* frame) override; 80 webrtc::DesktopCapturer::Result result,
81 std::unique_ptr<webrtc::DesktopFrame> frame) override;
81 82
82 // Method that is scheduled on |task_runner_| to be called on regular interval 83 // Method that is scheduled on |task_runner_| to be called on regular interval
83 // to capture a frame. 84 // to capture a frame.
84 void OnCaptureTimer(); 85 void OnCaptureTimer();
85 86
86 // Captures a frame and schedules timer for the next one. 87 // Captures a frame and schedules timer for the next one.
87 void CaptureFrameAndScheduleNext(); 88 void CaptureFrameAndScheduleNext();
88 89
89 // Captures a single frame. 90 // Captures a single frame.
90 void DoCapture(); 91 void DoCapture();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 CaptureFrameAndScheduleNext(); 184 CaptureFrameAndScheduleNext();
184 } 185 }
185 186
186 void DesktopCaptureDevice::Core::SetNotificationWindowId( 187 void DesktopCaptureDevice::Core::SetNotificationWindowId(
187 gfx::NativeViewId window_id) { 188 gfx::NativeViewId window_id) {
188 DCHECK(task_runner_->BelongsToCurrentThread()); 189 DCHECK(task_runner_->BelongsToCurrentThread());
189 DCHECK(window_id); 190 DCHECK(window_id);
190 desktop_capturer_->SetExcludedWindow(window_id); 191 desktop_capturer_->SetExcludedWindow(window_id);
191 } 192 }
192 193
193 void DesktopCaptureDevice::Core::OnCaptureCompleted( 194 void DesktopCaptureDevice::Core::OnCaptureResult(
194 webrtc::DesktopFrame* frame) { 195 webrtc::DesktopCapturer::Result result,
196 std::unique_ptr<webrtc::DesktopFrame> frame) {
195 DCHECK(task_runner_->BelongsToCurrentThread()); 197 DCHECK(task_runner_->BelongsToCurrentThread());
196 DCHECK(capture_in_progress_); 198 DCHECK(capture_in_progress_);
197 199
200 capture_in_progress_ = false;
201
202 bool success = result == webrtc::DesktopCapturer::Result::SUCCESS;
203
198 if (!first_capture_returned_) { 204 if (!first_capture_returned_) {
199 first_capture_returned_ = true; 205 first_capture_returned_ = true;
200 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) { 206 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
201 IncrementDesktopCaptureCounter(frame ? FIRST_SCREEN_CAPTURE_SUCCEEDED 207 IncrementDesktopCaptureCounter(success ? FIRST_SCREEN_CAPTURE_SUCCEEDED
202 : FIRST_SCREEN_CAPTURE_FAILED); 208 : FIRST_SCREEN_CAPTURE_FAILED);
203 } else { 209 } else {
204 IncrementDesktopCaptureCounter(frame ? FIRST_WINDOW_CAPTURE_SUCCEEDED 210 IncrementDesktopCaptureCounter(success ? FIRST_WINDOW_CAPTURE_SUCCEEDED
205 : FIRST_WINDOW_CAPTURE_FAILED); 211 : FIRST_WINDOW_CAPTURE_FAILED);
206 } 212 }
207 } 213 }
208 214
209 capture_in_progress_ = false; 215 if (!success) {
210 216 if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT)
211 if (!frame) { 217 client_->OnError(FROM_HERE, "The desktop capturer has failed.");
212 client_->OnError(FROM_HERE, "Failed to capture a frame.");
213 return; 218 return;
214 } 219 }
220 DCHECK(frame);
215 221
216 if (!client_) 222 if (!client_)
217 return; 223 return;
218 224
219 base::TimeDelta capture_time( 225 base::TimeDelta capture_time(
220 base::TimeDelta::FromMilliseconds(frame->capture_time_ms())); 226 base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
221 227
222 // The two UMA_ blocks must be put in its own scope since it creates a static 228 // The two UMA_ blocks must be put in its own scope since it creates a static
223 // variable which expected constant histogram name. 229 // variable which expected constant histogram name.
224 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) { 230 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
225 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time); 231 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
226 } else { 232 } else {
227 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time); 233 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
228 } 234 }
229 235
230 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
231
232 // If the frame size has changed, drop the output frame (if any), and 236 // If the frame size has changed, drop the output frame (if any), and
233 // determine the new output size. 237 // determine the new output size.
234 if (!previous_frame_size_.equals(frame->size())) { 238 if (!previous_frame_size_.equals(frame->size())) {
235 output_frame_.reset(); 239 output_frame_.reset();
236 resolution_chooser_->SetSourceSize(gfx::Size(frame->size().width(), 240 resolution_chooser_->SetSourceSize(gfx::Size(frame->size().width(),
237 frame->size().height())); 241 frame->size().height()));
238 previous_frame_size_ = frame->size(); 242 previous_frame_size_ = frame->size();
239 } 243 }
240 // Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so 244 // Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so
241 // it can convert the frame to I420 format. 245 // it can convert the frame to I420 format.
242 const webrtc::DesktopSize output_size( 246 const webrtc::DesktopSize output_size(
243 resolution_chooser_->capture_size().width() & ~1, 247 resolution_chooser_->capture_size().width() & ~1,
244 resolution_chooser_->capture_size().height() & ~1); 248 resolution_chooser_->capture_size().height() & ~1);
245 if (output_size.is_empty()) 249 if (output_size.is_empty())
246 return; 250 return;
247 251
252 webrtc::DesktopFrame* frame_ptr = frame.get();
253
248 // On OSX We receive a 1x1 frame when the shared window is minimized. It 254 // On OSX We receive a 1x1 frame when the shared window is minimized. It
249 // cannot be subsampled to I420 and will be dropped downstream. So we replace 255 // cannot be subsampled to I420 and will be dropped downstream. So we replace
250 // it with a black frame to avoid the video appearing frozen at the last 256 // it with a black frame to avoid the video appearing frozen at the last
251 // frame. 257 // frame.
252 if (frame->size().width() == 1 || frame->size().height() == 1) { 258 if (frame->size().width() == 1 || frame->size().height() == 1) {
253 if (!black_frame_) { 259 if (!black_frame_) {
254 black_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 260 black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
255 memset(black_frame_->data(), 261 memset(black_frame_->data(), 0,
256 0,
257 black_frame_->stride() * black_frame_->size().height()); 262 black_frame_->stride() * black_frame_->size().height());
258 } 263 }
259 owned_frame.reset(); 264 frame_ptr = black_frame_.get();
260 frame = black_frame_.get();
261 } 265 }
262 266
263 size_t output_bytes = output_size.width() * output_size.height() * 267 size_t output_bytes = output_size.width() * output_size.height() *
264 webrtc::DesktopFrame::kBytesPerPixel; 268 webrtc::DesktopFrame::kBytesPerPixel;
265 const uint8_t* output_data = NULL; 269 const uint8_t* output_data = NULL;
266 270
267 if (!frame->size().equals(output_size)) { 271 if (!frame_ptr->size().equals(output_size)) {
268 // Down-scale and/or letterbox to the target format if the frame does not 272 // Down-scale and/or letterbox to the target format if the frame does not
269 // match the output size. 273 // match the output size.
270 274
271 // Allocate a buffer of the correct size to scale the frame into. 275 // Allocate a buffer of the correct size to scale the frame into.
272 // |output_frame_| is cleared whenever the output size changes, so we don't 276 // |output_frame_| is cleared whenever the output size changes, so we don't
273 // need to worry about clearing out stale pixel data in letterboxed areas. 277 // need to worry about clearing out stale pixel data in letterboxed areas.
274 if (!output_frame_) { 278 if (!output_frame_) {
275 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 279 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
276 memset(output_frame_->data(), 0, output_bytes); 280 memset(output_frame_->data(), 0, output_bytes);
277 } 281 }
278 DCHECK(output_frame_->size().equals(output_size)); 282 DCHECK(output_frame_->size().equals(output_size));
279 283
280 // TODO(wez): Optimize this to scale only changed portions of the output, 284 // TODO(wez): Optimize this to scale only changed portions of the output,
281 // using ARGBScaleClip(). 285 // using ARGBScaleClip().
282 const webrtc::DesktopRect output_rect = 286 const webrtc::DesktopRect output_rect =
283 ComputeLetterboxRect(output_size, frame->size()); 287 ComputeLetterboxRect(output_size, frame_ptr->size());
284 uint8_t* output_rect_data = output_frame_->data() + 288 uint8_t* output_rect_data =
285 output_frame_->stride() * output_rect.top() + 289 output_frame_->GetFrameDataAtPos(output_rect.top_left());
286 webrtc::DesktopFrame::kBytesPerPixel * output_rect.left(); 290 libyuv::ARGBScale(frame_ptr->data(), frame_ptr->stride(),
287 libyuv::ARGBScale(frame->data(), frame->stride(), 291 frame_ptr->size().width(), frame_ptr->size().height(),
288 frame->size().width(), frame->size().height(),
289 output_rect_data, output_frame_->stride(), 292 output_rect_data, output_frame_->stride(),
290 output_rect.width(), output_rect.height(), 293 output_rect.width(), output_rect.height(),
291 libyuv::kFilterBilinear); 294 libyuv::kFilterBilinear);
292 output_data = output_frame_->data(); 295 output_data = output_frame_->data();
293 } else if (IsFrameUnpackedOrInverted(frame)) { 296 } else if (IsFrameUnpackedOrInverted(frame_ptr)) {
294 // If |frame| is not packed top-to-bottom then create a packed top-to-bottom 297 // If |frame| is not packed top-to-bottom then create a packed top-to-bottom
295 // copy. 298 // copy.
296 // This is required if the frame is inverted (see crbug.com/306876), or if 299 // This is required if the frame is inverted (see crbug.com/306876), or if
297 // |frame| is cropped form a larger frame (see crbug.com/437740). 300 // |frame| is cropped form a larger frame (see crbug.com/437740).
298 if (!output_frame_) { 301 if (!output_frame_) {
299 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 302 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
300 memset(output_frame_->data(), 0, output_bytes); 303 memset(output_frame_->data(), 0, output_bytes);
301 } 304 }
302 305
303 output_frame_->CopyPixelsFrom( 306 output_frame_->CopyPixelsFrom(
304 *frame, 307 *frame, webrtc::DesktopVector(),
305 webrtc::DesktopVector(), 308 webrtc::DesktopRect::MakeSize(frame_ptr->size()));
306 webrtc::DesktopRect::MakeSize(frame->size()));
307 output_data = output_frame_->data(); 309 output_data = output_frame_->data();
308 } else { 310 } else {
309 // If the captured frame matches the output size, we can return the pixel 311 // If the captured frame matches the output size, we can return the pixel
310 // data directly. 312 // data directly.
311 output_data = frame->data(); 313 output_data = frame_ptr->data();
312 } 314 }
313 315
314 base::TimeTicks now = base::TimeTicks::Now(); 316 base::TimeTicks now = base::TimeTicks::Now();
315 if (first_ref_time_.is_null()) 317 if (first_ref_time_.is_null())
316 first_ref_time_ = now; 318 first_ref_time_ = now;
317 client_->OnIncomingCapturedData( 319 client_->OnIncomingCapturedData(
318 output_data, output_bytes, 320 output_data, output_bytes,
319 media::VideoCaptureFormat( 321 media::VideoCaptureFormat(
320 gfx::Size(output_size.width(), output_size.height()), 322 gfx::Size(output_size.width(), output_size.height()),
321 requested_frame_rate_, media::PIXEL_FORMAT_ARGB), 323 requested_frame_rate_, media::PIXEL_FORMAT_ARGB),
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 #else 457 #else
456 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT; 458 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT;
457 #endif 459 #endif
458 460
459 thread_.StartWithOptions(base::Thread::Options(thread_type, 0)); 461 thread_.StartWithOptions(base::Thread::Options(thread_type, 0));
460 462
461 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type)); 463 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type));
462 } 464 }
463 465
464 } // namespace content 466 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698