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

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: fix chromeos 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_);
199 capture_in_progress_ = false;
200
201 bool success = result == webrtc::DesktopCapturer::Result::SUCCESS;
197 202
198 if (!first_capture_returned_) { 203 if (!first_capture_returned_) {
199 first_capture_returned_ = true; 204 first_capture_returned_ = true;
200 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) { 205 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
201 IncrementDesktopCaptureCounter(frame ? FIRST_SCREEN_CAPTURE_SUCCEEDED 206 IncrementDesktopCaptureCounter(success ? FIRST_SCREEN_CAPTURE_SUCCEEDED
202 : FIRST_SCREEN_CAPTURE_FAILED); 207 : FIRST_SCREEN_CAPTURE_FAILED);
203 } else { 208 } else {
204 IncrementDesktopCaptureCounter(frame ? FIRST_WINDOW_CAPTURE_SUCCEEDED 209 IncrementDesktopCaptureCounter(success ? FIRST_WINDOW_CAPTURE_SUCCEEDED
205 : FIRST_WINDOW_CAPTURE_FAILED); 210 : FIRST_WINDOW_CAPTURE_FAILED);
206 } 211 }
207 } 212 }
208 213
209 capture_in_progress_ = false; 214 if (!success) {
210 215 if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT)
211 if (!frame) { 216 client_->OnError(FROM_HERE, "The desktop capturer has failed.");
212 client_->OnError(FROM_HERE, "Failed to capture a frame.");
213 return; 217 return;
214 } 218 }
219 DCHECK(frame);
215 220
216 if (!client_) 221 if (!client_)
217 return; 222 return;
218 223
219 base::TimeDelta capture_time( 224 base::TimeDelta capture_time(
220 base::TimeDelta::FromMilliseconds(frame->capture_time_ms())); 225 base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
221 226
222 // The two UMA_ blocks must be put in its own scope since it creates a static 227 // The two UMA_ blocks must be put in its own scope since it creates a static
223 // variable which expected constant histogram name. 228 // variable which expected constant histogram name.
224 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) { 229 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
225 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time); 230 UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
226 } else { 231 } else {
227 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time); 232 UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
228 } 233 }
229 234
230 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
231
232 // If the frame size has changed, drop the output frame (if any), and 235 // If the frame size has changed, drop the output frame (if any), and
233 // determine the new output size. 236 // determine the new output size.
234 if (!previous_frame_size_.equals(frame->size())) { 237 if (!previous_frame_size_.equals(frame->size())) {
235 output_frame_.reset(); 238 output_frame_.reset();
236 resolution_chooser_->SetSourceSize(gfx::Size(frame->size().width(), 239 resolution_chooser_->SetSourceSize(gfx::Size(frame->size().width(),
237 frame->size().height())); 240 frame->size().height()));
238 previous_frame_size_ = frame->size(); 241 previous_frame_size_ = frame->size();
239 } 242 }
240 // Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so 243 // Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so
241 // it can convert the frame to I420 format. 244 // it can convert the frame to I420 format.
242 const webrtc::DesktopSize output_size( 245 const webrtc::DesktopSize output_size(
243 resolution_chooser_->capture_size().width() & ~1, 246 resolution_chooser_->capture_size().width() & ~1,
244 resolution_chooser_->capture_size().height() & ~1); 247 resolution_chooser_->capture_size().height() & ~1);
245 if (output_size.is_empty()) 248 if (output_size.is_empty())
246 return; 249 return;
247 250
248 // On OSX We receive a 1x1 frame when the shared window is minimized. It 251 size_t output_bytes = output_size.width() * output_size.height() *
249 // cannot be subsampled to I420 and will be dropped downstream. So we replace 252 webrtc::DesktopFrame::kBytesPerPixel;
250 // it with a black frame to avoid the video appearing frozen at the last 253 const uint8_t* output_data = nullptr;
251 // frame. 254
252 if (frame->size().width() == 1 || frame->size().height() == 1) { 255 if (frame->size().equals(webrtc::DesktopSize(1, 1))) {
253 if (!black_frame_) { 256 // On OSX We receive a 1x1 frame when the shared window is minimized. It
257 // cannot be subsampled to I420 and will be dropped downstream. So we
258 // replace it with a black frame to avoid the video appearing frozen at the
259 // last frame.
260 if (!black_frame_ || !black_frame_->size().equals(output_size)) {
254 black_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 261 black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
255 memset(black_frame_->data(), 262 memset(black_frame_->data(), 0,
256 0,
257 black_frame_->stride() * black_frame_->size().height()); 263 black_frame_->stride() * black_frame_->size().height());
258 } 264 }
259 owned_frame.reset(); 265 output_data = black_frame_->data();
260 frame = black_frame_.get(); 266 } else if (!frame->size().equals(output_size)) {
261 }
262
263 size_t output_bytes = output_size.width() * output_size.height() *
264 webrtc::DesktopFrame::kBytesPerPixel;
265 const uint8_t* output_data = NULL;
266
267 if (!frame->size().equals(output_size)) {
268 // Down-scale and/or letterbox to the target format if the frame does not 267 // Down-scale and/or letterbox to the target format if the frame does not
269 // match the output size. 268 // match the output size.
270 269
271 // Allocate a buffer of the correct size to scale the frame into. 270 // 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 271 // |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. 272 // need to worry about clearing out stale pixel data in letterboxed areas.
274 if (!output_frame_) { 273 if (!output_frame_) {
275 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 274 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
276 memset(output_frame_->data(), 0, output_bytes); 275 memset(output_frame_->data(), 0, output_bytes);
277 } 276 }
278 DCHECK(output_frame_->size().equals(output_size)); 277 DCHECK(output_frame_->size().equals(output_size));
279 278
280 // TODO(wez): Optimize this to scale only changed portions of the output, 279 // TODO(wez): Optimize this to scale only changed portions of the output,
281 // using ARGBScaleClip(). 280 // using ARGBScaleClip().
282 const webrtc::DesktopRect output_rect = 281 const webrtc::DesktopRect output_rect =
283 ComputeLetterboxRect(output_size, frame->size()); 282 ComputeLetterboxRect(output_size, frame->size());
284 uint8_t* output_rect_data = output_frame_->data() + 283 uint8_t* output_rect_data =
285 output_frame_->stride() * output_rect.top() + 284 output_frame_->GetFrameDataAtPos(output_rect.top_left());
286 webrtc::DesktopFrame::kBytesPerPixel * output_rect.left(); 285 libyuv::ARGBScale(frame->data(), frame->stride(), frame->size().width(),
287 libyuv::ARGBScale(frame->data(), frame->stride(), 286 frame->size().height(), output_rect_data,
288 frame->size().width(), frame->size().height(), 287 output_frame_->stride(), output_rect.width(),
289 output_rect_data, output_frame_->stride(), 288 output_rect.height(), libyuv::kFilterBilinear);
290 output_rect.width(), output_rect.height(),
291 libyuv::kFilterBilinear);
292 output_data = output_frame_->data(); 289 output_data = output_frame_->data();
293 } else if (IsFrameUnpackedOrInverted(frame)) { 290 } else if (IsFrameUnpackedOrInverted(frame.get())) {
294 // If |frame| is not packed top-to-bottom then create a packed top-to-bottom 291 // If |frame| is not packed top-to-bottom then create a packed top-to-bottom
295 // copy. 292 // copy.
296 // This is required if the frame is inverted (see crbug.com/306876), or if 293 // 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). 294 // |frame| is cropped form a larger frame (see crbug.com/437740).
298 if (!output_frame_) { 295 if (!output_frame_) {
299 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); 296 output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
300 memset(output_frame_->data(), 0, output_bytes); 297 memset(output_frame_->data(), 0, output_bytes);
301 } 298 }
302 299
303 output_frame_->CopyPixelsFrom( 300 output_frame_->CopyPixelsFrom(*frame, webrtc::DesktopVector(),
304 *frame, 301 webrtc::DesktopRect::MakeSize(frame->size()));
305 webrtc::DesktopVector(),
306 webrtc::DesktopRect::MakeSize(frame->size()));
307 output_data = output_frame_->data(); 302 output_data = output_frame_->data();
308 } else { 303 } else {
309 // If the captured frame matches the output size, we can return the pixel 304 // If the captured frame matches the output size, we can return the pixel
310 // data directly. 305 // data directly.
311 output_data = frame->data(); 306 output_data = frame->data();
312 } 307 }
313 308
314 base::TimeTicks now = base::TimeTicks::Now(); 309 base::TimeTicks now = base::TimeTicks::Now();
315 if (first_ref_time_.is_null()) 310 if (first_ref_time_.is_null())
316 first_ref_time_ = now; 311 first_ref_time_ = now;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 #else 450 #else
456 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT; 451 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT;
457 #endif 452 #endif
458 453
459 thread_.StartWithOptions(base::Thread::Options(thread_type, 0)); 454 thread_.StartWithOptions(base::Thread::Options(thread_type, 0));
460 455
461 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type)); 456 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type));
462 } 457 }
463 458
464 } // namespace content 459 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698