| 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(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 100 virtual bool Start( |
| 101 const media::VideoCaptureParams& params) OVERRIDE; | 101 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) 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 | |
| 168 // YUV readback pipeline. | 165 // YUV readback pipeline. |
| 169 scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_; | 166 scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_; |
| 170 | 167 |
| 171 // Cursor state. | 168 // Cursor state. |
| 172 ui::Cursor last_cursor_; | 169 ui::Cursor last_cursor_; |
| 173 gfx::Point cursor_hot_point_; | 170 gfx::Point cursor_hot_point_; |
| 174 SkBitmap scaled_cursor_bitmap_; | 171 SkBitmap scaled_cursor_bitmap_; |
| 175 | 172 |
| 176 DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine); | 173 DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine); |
| 177 }; | 174 }; |
| 178 | 175 |
| 179 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine( | 176 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine( |
| 180 const DesktopMediaID& source) | 177 const DesktopMediaID& source) |
| 181 : desktop_window_(NULL), | 178 : desktop_window_(NULL), |
| 182 desktop_layer_(NULL), | 179 desktop_layer_(NULL), |
| 183 timer_(true, true), | 180 timer_(true, true), |
| 184 window_id_(source) {} | 181 window_id_(source) {} |
| 185 | 182 |
| 186 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {} | 183 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {} |
| 187 | 184 |
| 188 bool DesktopVideoCaptureMachine::Start( | 185 bool DesktopVideoCaptureMachine::Start( |
| 189 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 186 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) { |
| 190 const media::VideoCaptureParams& params) { | |
| 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 192 | 188 |
| 193 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_); | 189 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_); |
| 194 if (!desktop_window_) | 190 if (!desktop_window_) |
| 195 return false; | 191 return false; |
| 196 | 192 |
| 197 // If the desktop layer is already destroyed then return failure. | 193 // If the desktop layer is already destroyed then return failure. |
| 198 desktop_layer_ = desktop_window_->layer(); | 194 desktop_layer_ = desktop_window_->layer(); |
| 199 if (!desktop_layer_) | 195 if (!desktop_layer_) |
| 200 return false; | 196 return false; |
| 201 | 197 |
| 202 DCHECK(oracle_proxy.get()); | 198 DCHECK(oracle_proxy.get()); |
| 203 oracle_proxy_ = oracle_proxy; | 199 oracle_proxy_ = oracle_proxy; |
| 204 capture_params_ = params; | |
| 205 | 200 |
| 206 // Update capture size. | 201 // Update capture size. |
| 207 UpdateCaptureSize(); | 202 UpdateCaptureSize(); |
| 208 | 203 |
| 209 // Start observing window events. | 204 // Start observing window events. |
| 210 desktop_window_->AddObserver(this); | 205 desktop_window_->AddObserver(this); |
| 211 | 206 |
| 212 // Start observing compositor updates. | 207 // Start observing compositor updates. |
| 213 ui::Compositor* compositor = desktop_layer_->GetCompositor(); | 208 ui::Compositor* compositor = desktop_layer_->GetCompositor(); |
| 214 if (!compositor) | 209 if (!compositor) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 base::TimeTicks start_time, | 287 base::TimeTicks start_time, |
| 293 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 288 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
| 294 const scoped_refptr<media::VideoFrame>& target, | 289 const scoped_refptr<media::VideoFrame>& target, |
| 295 const SkBitmap& cursor_bitmap, | 290 const SkBitmap& cursor_bitmap, |
| 296 const gfx::Point& cursor_position, | 291 const gfx::Point& cursor_position, |
| 297 scoped_ptr<cc::SingleReleaseCallback> release_callback, | 292 scoped_ptr<cc::SingleReleaseCallback> release_callback, |
| 298 bool result) { | 293 bool result) { |
| 299 if (!cursor_bitmap.isNull()) | 294 if (!cursor_bitmap.isNull()) |
| 300 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); | 295 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); |
| 301 release_callback->Run(0, false); | 296 release_callback->Run(0, false); |
| 302 capture_frame_cb.Run(target, start_time, result); | 297 capture_frame_cb.Run(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); | |
| 310 } | 298 } |
| 311 | 299 |
| 312 void DesktopVideoCaptureMachine::DidCopyOutput( | 300 void DesktopVideoCaptureMachine::DidCopyOutput( |
| 313 scoped_refptr<media::VideoFrame> video_frame, | 301 scoped_refptr<media::VideoFrame> video_frame, |
| 314 base::TimeTicks start_time, | 302 base::TimeTicks start_time, |
| 315 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 303 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
| 316 scoped_ptr<cc::CopyOutputResult> result) { | 304 scoped_ptr<cc::CopyOutputResult> result) { |
| 317 static bool first_call = true; | 305 static bool first_call = true; |
| 318 | 306 |
| 319 bool succeeded = ProcessCopyOutputResponse( | 307 bool succeeded = ProcessCopyOutputResponse( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 339 } | 327 } |
| 340 | 328 |
| 341 bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse( | 329 bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse( |
| 342 scoped_refptr<media::VideoFrame> video_frame, | 330 scoped_refptr<media::VideoFrame> video_frame, |
| 343 base::TimeTicks start_time, | 331 base::TimeTicks start_time, |
| 344 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 332 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, |
| 345 scoped_ptr<cc::CopyOutputResult> result) { | 333 scoped_ptr<cc::CopyOutputResult> result) { |
| 346 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_layer_) | 334 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_layer_) |
| 347 return false; | 335 return false; |
| 348 | 336 |
| 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 | |
| 372 // Compute the dest size we want after the letterboxing resize. Make the | 337 // Compute the dest size we want after the letterboxing resize. Make the |
| 373 // coordinates and sizes even because we letterbox in YUV space | 338 // coordinates and sizes even because we letterbox in YUV space |
| 374 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to | 339 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to |
| 375 // line up correctly. | 340 // line up correctly. |
| 376 // The video frame's coded_size() and the result's size() are both physical | 341 // The video frame's coded_size() and the result's size() are both physical |
| 377 // pixels. | 342 // pixels. |
| 378 gfx::Rect region_in_frame = | 343 gfx::Rect region_in_frame = |
| 379 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()), | 344 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()), |
| 380 result->size()); | 345 result->size()); |
| 381 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, | 346 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 IncrementDesktopCaptureCounter(source.type == DesktopMediaID::TYPE_SCREEN | 475 IncrementDesktopCaptureCounter(source.type == DesktopMediaID::TYPE_SCREEN |
| 511 ? SCREEN_CAPTURER_CREATED | 476 ? SCREEN_CAPTURER_CREATED |
| 512 : WINDOW_CATPTURER_CREATED); | 477 : WINDOW_CATPTURER_CREATED); |
| 513 return new DesktopCaptureDeviceAura(source); | 478 return new DesktopCaptureDeviceAura(source); |
| 514 } | 479 } |
| 515 | 480 |
| 516 void DesktopCaptureDeviceAura::AllocateAndStart( | 481 void DesktopCaptureDeviceAura::AllocateAndStart( |
| 517 const media::VideoCaptureParams& params, | 482 const media::VideoCaptureParams& params, |
| 518 scoped_ptr<Client> client) { | 483 scoped_ptr<Client> client) { |
| 519 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 484 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
| 520 media::VideoCaptureParams new_params = params; | 485 core_->AllocateAndStart(params, client.Pass()); |
| 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()); | |
| 525 } | 486 } |
| 526 | 487 |
| 527 void DesktopCaptureDeviceAura::StopAndDeAllocate() { | 488 void DesktopCaptureDeviceAura::StopAndDeAllocate() { |
| 528 core_->StopAndDeAllocate(); | 489 core_->StopAndDeAllocate(); |
| 529 } | 490 } |
| 530 | 491 |
| 531 } // namespace content | 492 } // namespace content |
| OLD | NEW |