OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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_aura.h" | 5 #include "content/browser/media/capture/desktop_capture_device_aura.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/timer/timer.h" | 9 #include "base/timer/timer.h" |
10 #include "cc/output/copy_output_request.h" | 10 #include "cc/output/copy_output_request.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 class DesktopVideoCaptureMachine | 90 class DesktopVideoCaptureMachine |
91 : public VideoCaptureMachine, | 91 : public VideoCaptureMachine, |
92 public aura::WindowObserver, | 92 public aura::WindowObserver, |
93 public ui::CompositorObserver, | 93 public ui::CompositorObserver, |
94 public base::SupportsWeakPtr<DesktopVideoCaptureMachine> { | 94 public base::SupportsWeakPtr<DesktopVideoCaptureMachine> { |
95 public: | 95 public: |
96 DesktopVideoCaptureMachine(const DesktopMediaID& source); | 96 DesktopVideoCaptureMachine(const DesktopMediaID& source); |
97 virtual ~DesktopVideoCaptureMachine(); | 97 virtual ~DesktopVideoCaptureMachine(); |
98 | 98 |
99 // VideoCaptureFrameSource overrides. | 99 // VideoCaptureFrameSource overrides. |
100 virtual bool Start( | 100 virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
101 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) OVERRIDE; | 101 const media::VideoCaptureParams& params) OVERRIDE; |
102 virtual void Stop(const base::Closure& callback) OVERRIDE; | 102 virtual void Stop(const base::Closure& callback) OVERRIDE; |
103 | 103 |
104 // Implements aura::WindowObserver. | 104 // Implements aura::WindowObserver. |
105 virtual void OnWindowBoundsChanged(aura::Window* window, | 105 virtual void OnWindowBoundsChanged(aura::Window* window, |
106 const gfx::Rect& old_bounds, | 106 const gfx::Rect& old_bounds, |
107 const gfx::Rect& new_bounds) OVERRIDE; | 107 const gfx::Rect& new_bounds) OVERRIDE; |
108 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; | 108 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; |
109 | 109 |
110 // Implements ui::CompositorObserver. | 110 // Implements ui::CompositorObserver. |
111 virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {} | 111 virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {} |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 155 |
156 // The timer that kicks off period captures. | 156 // The timer that kicks off period captures. |
157 base::Timer timer_; | 157 base::Timer timer_; |
158 | 158 |
159 // The id of the window being captured. | 159 // The id of the window being captured. |
160 DesktopMediaID window_id_; | 160 DesktopMediaID window_id_; |
161 | 161 |
162 // Makes all the decisions about which frames to copy, and how. | 162 // Makes all the decisions about which frames to copy, and how. |
163 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; | 163 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; |
164 | 164 |
| 165 // The capture parameters for this capture. |
| 166 media::VideoCaptureParams capture_params_; |
| 167 |
165 // YUV readback pipeline. | 168 // YUV readback pipeline. |
166 scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_; | 169 scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_; |
167 | 170 |
168 // Cursor state. | 171 // Cursor state. |
169 ui::Cursor last_cursor_; | 172 ui::Cursor last_cursor_; |
170 gfx::Point cursor_hot_point_; | 173 gfx::Point cursor_hot_point_; |
171 SkBitmap scaled_cursor_bitmap_; | 174 SkBitmap scaled_cursor_bitmap_; |
172 | 175 |
173 DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine); | 176 DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine); |
174 }; | 177 }; |
175 | 178 |
176 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine( | 179 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine( |
177 const DesktopMediaID& source) | 180 const DesktopMediaID& source) |
178 : desktop_window_(NULL), | 181 : desktop_window_(NULL), |
179 desktop_layer_(NULL), | 182 desktop_layer_(NULL), |
180 timer_(true, true), | 183 timer_(true, true), |
181 window_id_(source) {} | 184 window_id_(source) {} |
182 | 185 |
183 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {} | 186 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {} |
184 | 187 |
185 bool DesktopVideoCaptureMachine::Start( | 188 bool DesktopVideoCaptureMachine::Start( |
186 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) { | 189 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
| 190 const media::VideoCaptureParams& params) { |
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
188 | 192 |
189 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_); | 193 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_); |
190 if (!desktop_window_) | 194 if (!desktop_window_) |
191 return false; | 195 return false; |
192 | 196 |
193 // If the desktop layer is already destroyed then return failure. | 197 // If the desktop layer is already destroyed then return failure. |
194 desktop_layer_ = desktop_window_->layer(); | 198 desktop_layer_ = desktop_window_->layer(); |
195 if (!desktop_layer_) | 199 if (!desktop_layer_) |
196 return false; | 200 return false; |
197 | 201 |
198 DCHECK(oracle_proxy.get()); | 202 DCHECK(oracle_proxy.get()); |
199 oracle_proxy_ = oracle_proxy; | 203 oracle_proxy_ = oracle_proxy; |
| 204 capture_params_ = params; |
200 | 205 |
201 // Update capture size. | 206 // Update capture size. |
202 UpdateCaptureSize(); | 207 UpdateCaptureSize(); |
203 | 208 |
204 // Start observing window events. | 209 // Start observing window events. |
205 desktop_window_->AddObserver(this); | 210 desktop_window_->AddObserver(this); |
206 | 211 |
207 // Start observing compositor updates. | 212 // Start observing compositor updates. |
208 ui::Compositor* compositor = desktop_layer_->GetCompositor(); | 213 ui::Compositor* compositor = desktop_layer_->GetCompositor(); |
209 if (!compositor) | 214 if (!compositor) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 base::TimeTicks start_time, | 292 base::TimeTicks start_time, |
288 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 293 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
289 const scoped_refptr<media::VideoFrame>& target, | 294 const scoped_refptr<media::VideoFrame>& target, |
290 const SkBitmap& cursor_bitmap, | 295 const SkBitmap& cursor_bitmap, |
291 const gfx::Point& cursor_position, | 296 const gfx::Point& cursor_position, |
292 scoped_ptr<cc::SingleReleaseCallback> release_callback, | 297 scoped_ptr<cc::SingleReleaseCallback> release_callback, |
293 bool result) { | 298 bool result) { |
294 if (!cursor_bitmap.isNull()) | 299 if (!cursor_bitmap.isNull()) |
295 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); | 300 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); |
296 release_callback->Run(0, false); | 301 release_callback->Run(0, false); |
297 capture_frame_cb.Run(start_time, result); | 302 capture_frame_cb.Run(target, start_time, result); |
| 303 } |
| 304 |
| 305 void RunSingleReleaseCallback(scoped_ptr<cc::SingleReleaseCallback> cb, |
| 306 const std::vector<uint32>& sync_points) { |
| 307 // TODO(hshi): handle release of multiple sync points. |
| 308 DCHECK_EQ(1u, sync_points.size()); |
| 309 cb->Run(sync_points[0], false); |
298 } | 310 } |
299 | 311 |
300 void DesktopVideoCaptureMachine::DidCopyOutput( | 312 void DesktopVideoCaptureMachine::DidCopyOutput( |
301 scoped_refptr<media::VideoFrame> video_frame, | 313 scoped_refptr<media::VideoFrame> video_frame, |
302 base::TimeTicks start_time, | 314 base::TimeTicks start_time, |
303 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 315 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
304 scoped_ptr<cc::CopyOutputResult> result) { | 316 scoped_ptr<cc::CopyOutputResult> result) { |
305 static bool first_call = true; | 317 static bool first_call = true; |
306 | 318 |
307 bool succeeded = ProcessCopyOutputResponse( | 319 bool succeeded = ProcessCopyOutputResponse( |
(...skipping 19 matching lines...) Expand all Loading... |
327 } | 339 } |
328 | 340 |
329 bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse( | 341 bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse( |
330 scoped_refptr<media::VideoFrame> video_frame, | 342 scoped_refptr<media::VideoFrame> video_frame, |
331 base::TimeTicks start_time, | 343 base::TimeTicks start_time, |
332 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 344 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
333 scoped_ptr<cc::CopyOutputResult> result) { | 345 scoped_ptr<cc::CopyOutputResult> result) { |
334 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_layer_) | 346 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_layer_) |
335 return false; | 347 return false; |
336 | 348 |
| 349 if (capture_params_.requested_format.pixel_format == |
| 350 media::PIXEL_FORMAT_TEXTURE) { |
| 351 DCHECK(!video_frame); |
| 352 cc::TextureMailbox texture_mailbox; |
| 353 scoped_ptr<cc::SingleReleaseCallback> release_callback; |
| 354 result->TakeTexture(&texture_mailbox, &release_callback); |
| 355 DCHECK(texture_mailbox.IsTexture()); |
| 356 if (!texture_mailbox.IsTexture()) |
| 357 return false; |
| 358 video_frame = media::VideoFrame::WrapNativeTexture( |
| 359 make_scoped_ptr(new gpu::MailboxHolder(texture_mailbox.mailbox(), |
| 360 texture_mailbox.target(), |
| 361 texture_mailbox.sync_point())), |
| 362 base::Bind(&RunSingleReleaseCallback, base::Passed(&release_callback)), |
| 363 result->size(), |
| 364 gfx::Rect(result->size()), |
| 365 result->size(), |
| 366 base::TimeDelta(), |
| 367 media::VideoFrame::ReadPixelsCB()); |
| 368 capture_frame_cb.Run(video_frame, start_time, true); |
| 369 return true; |
| 370 } |
| 371 |
337 // Compute the dest size we want after the letterboxing resize. Make the | 372 // Compute the dest size we want after the letterboxing resize. Make the |
338 // coordinates and sizes even because we letterbox in YUV space | 373 // coordinates and sizes even because we letterbox in YUV space |
339 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to | 374 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to |
340 // line up correctly. | 375 // line up correctly. |
341 // The video frame's coded_size() and the result's size() are both physical | 376 // The video frame's coded_size() and the result's size() are both physical |
342 // pixels. | 377 // pixels. |
343 gfx::Rect region_in_frame = | 378 gfx::Rect region_in_frame = |
344 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()), | 379 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()), |
345 result->size()); | 380 result->size()); |
346 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, | 381 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 IncrementDesktopCaptureCounter(source.type == DesktopMediaID::TYPE_SCREEN | 510 IncrementDesktopCaptureCounter(source.type == DesktopMediaID::TYPE_SCREEN |
476 ? SCREEN_CAPTURER_CREATED | 511 ? SCREEN_CAPTURER_CREATED |
477 : WINDOW_CATPTURER_CREATED); | 512 : WINDOW_CATPTURER_CREATED); |
478 return new DesktopCaptureDeviceAura(source); | 513 return new DesktopCaptureDeviceAura(source); |
479 } | 514 } |
480 | 515 |
481 void DesktopCaptureDeviceAura::AllocateAndStart( | 516 void DesktopCaptureDeviceAura::AllocateAndStart( |
482 const media::VideoCaptureParams& params, | 517 const media::VideoCaptureParams& params, |
483 scoped_ptr<Client> client) { | 518 scoped_ptr<Client> client) { |
484 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 519 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
485 core_->AllocateAndStart(params, client.Pass()); | 520 media::VideoCaptureParams new_params = params; |
| 521 // Desktop capture devices ignore the requested size and return the actual |
| 522 // captured desktop size. |
| 523 new_params.requested_format.frame_size.SetSize(0, 0); |
| 524 core_->AllocateAndStart(new_params, client.Pass()); |
486 } | 525 } |
487 | 526 |
488 void DesktopCaptureDeviceAura::StopAndDeAllocate() { | 527 void DesktopCaptureDeviceAura::StopAndDeAllocate() { |
489 core_->StopAndDeAllocate(); | 528 core_->StopAndDeAllocate(); |
490 } | 529 } |
491 | 530 |
492 } // namespace content | 531 } // namespace content |
OLD | NEW |