| 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/aura_window_capture_machine.h" | 5 #include "content/browser/media/capture/aura_window_capture_machine.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" |
| 11 #include "cc/output/copy_output_result.h" | 11 #include "cc/output/copy_output_result.h" |
| 12 #include "content/browser/compositor/image_transport_factory.h" | 12 #include "content/browser/compositor/image_transport_factory.h" |
| 13 #include "content/browser/media/capture/content_video_capture_device_core.h" | |
| 14 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" | 13 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" |
| 15 #include "content/common/gpu/client/gl_helper.h" | 14 #include "content/common/gpu/client/gl_helper.h" |
| 16 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 17 #include "content/public/browser/power_save_blocker.h" | 16 #include "content/public/browser/power_save_blocker.h" |
| 18 #include "media/base/video_capture_types.h" | 17 #include "media/base/video_capture_types.h" |
| 19 #include "media/base/video_util.h" | 18 #include "media/base/video_util.h" |
| 19 #include "media/capture/thread_safe_capture_oracle.h" |
| 20 #include "media/capture/video_capture_oracle.h" |
| 20 #include "skia/ext/image_operations.h" | 21 #include "skia/ext/image_operations.h" |
| 21 #include "third_party/skia/include/core/SkBitmap.h" | 22 #include "third_party/skia/include/core/SkBitmap.h" |
| 22 #include "ui/aura/client/screen_position_client.h" | 23 #include "ui/aura/client/screen_position_client.h" |
| 23 #include "ui/aura/env.h" | 24 #include "ui/aura/env.h" |
| 24 #include "ui/aura/window.h" | 25 #include "ui/aura/window.h" |
| 25 #include "ui/aura/window_observer.h" | 26 #include "ui/aura/window_observer.h" |
| 26 #include "ui/aura/window_tree_host.h" | 27 #include "ui/aura/window_tree_host.h" |
| 27 #include "ui/base/cursor/cursors_aura.h" | 28 #include "ui/base/cursor/cursors_aura.h" |
| 28 #include "ui/compositor/compositor.h" | 29 #include "ui/compositor/compositor.h" |
| 29 #include "ui/compositor/dip_util.h" | 30 #include "ui/compositor/dip_util.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 int color_v = clip_byte(((color_r * 112 + color_g * -94 + | 83 int color_v = clip_byte(((color_r * 112 + color_g * -94 + |
| 83 color_b * -18 + 128) >> 8) + 128); | 84 color_b * -18 + 128) >> 8) + 128); |
| 84 uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]); | 85 uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]); |
| 85 vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]); | 86 vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]); |
| 86 } | 87 } |
| 87 } | 88 } |
| 88 } | 89 } |
| 89 cursor_bitmap.unlockPixels(); | 90 cursor_bitmap.unlockPixels(); |
| 90 } | 91 } |
| 91 | 92 |
| 93 using CaptureFrameCallback = |
| 94 media::ThreadSafeCaptureOracle::CaptureFrameCallback; |
| 95 |
| 92 void CopyOutputFinishedForVideo( | 96 void CopyOutputFinishedForVideo( |
| 93 base::TimeTicks start_time, | 97 base::TimeTicks start_time, |
| 94 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 98 const CaptureFrameCallback& capture_frame_cb, |
| 95 const scoped_refptr<media::VideoFrame>& target, | 99 const scoped_refptr<media::VideoFrame>& target, |
| 96 const SkBitmap& cursor_bitmap, | 100 const SkBitmap& cursor_bitmap, |
| 97 const gfx::Point& cursor_position, | 101 const gfx::Point& cursor_position, |
| 98 scoped_ptr<cc::SingleReleaseCallback> release_callback, | 102 scoped_ptr<cc::SingleReleaseCallback> release_callback, |
| 99 bool result) { | 103 bool result) { |
| 100 if (!cursor_bitmap.isNull()) | 104 if (!cursor_bitmap.isNull()) |
| 101 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); | 105 RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position); |
| 102 release_callback->Run(0, false); | 106 release_callback->Run(0, false); |
| 103 capture_frame_cb.Run(target, start_time, result); | 107 capture_frame_cb.Run(target, start_time, result); |
| 104 } | 108 } |
| 105 | 109 |
| 106 void RunSingleReleaseCallback(scoped_ptr<cc::SingleReleaseCallback> cb, | 110 void RunSingleReleaseCallback(scoped_ptr<cc::SingleReleaseCallback> cb, |
| 107 uint32 sync_point) { | 111 uint32 sync_point) { |
| 108 cb->Run(sync_point, false); | 112 cb->Run(sync_point, false); |
| 109 } | 113 } |
| 110 | 114 |
| 111 } // namespace | 115 } // namespace |
| 112 | 116 |
| 113 AuraWindowCaptureMachine::AuraWindowCaptureMachine() | 117 AuraWindowCaptureMachine::AuraWindowCaptureMachine() |
| 114 : desktop_window_(NULL), | 118 : desktop_window_(NULL), |
| 115 timer_(true, true), | 119 timer_(true, true), |
| 116 screen_capture_(false) {} | 120 screen_capture_(false) {} |
| 117 | 121 |
| 118 AuraWindowCaptureMachine::~AuraWindowCaptureMachine() {} | 122 AuraWindowCaptureMachine::~AuraWindowCaptureMachine() {} |
| 119 | 123 |
| 120 bool AuraWindowCaptureMachine::Start( | 124 void AuraWindowCaptureMachine::Start( |
| 121 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 125 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
| 126 const media::VideoCaptureParams& params, |
| 127 const base::Callback<void(bool)> callback) { |
| 128 // Starts the capture machine asynchronously. |
| 129 BrowserThread::PostTaskAndReplyWithResult( |
| 130 BrowserThread::UI, |
| 131 FROM_HERE, |
| 132 base::Bind(&AuraWindowCaptureMachine::InternalStart, |
| 133 base::Unretained(this), |
| 134 oracle_proxy, |
| 135 params), |
| 136 callback); |
| 137 } |
| 138 |
| 139 bool AuraWindowCaptureMachine::InternalStart( |
| 140 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
| 122 const media::VideoCaptureParams& params) { | 141 const media::VideoCaptureParams& params) { |
| 123 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 142 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 124 | 143 |
| 125 // The window might be destroyed between SetWindow() and Start(). | 144 // The window might be destroyed between SetWindow() and Start(). |
| 126 if (!desktop_window_) | 145 if (!desktop_window_) |
| 127 return false; | 146 return false; |
| 128 | 147 |
| 129 // If the associated layer is already destroyed then return failure. | 148 // If the associated layer is already destroyed then return failure. |
| 130 ui::Layer* layer = desktop_window_->layer(); | 149 ui::Layer* layer = desktop_window_->layer(); |
| 131 if (!layer) | 150 if (!layer) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 144 | 163 |
| 145 power_save_blocker_.reset( | 164 power_save_blocker_.reset( |
| 146 PowerSaveBlocker::Create( | 165 PowerSaveBlocker::Create( |
| 147 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, | 166 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, |
| 148 PowerSaveBlocker::kReasonOther, | 167 PowerSaveBlocker::kReasonOther, |
| 149 "DesktopCaptureDevice is running").release()); | 168 "DesktopCaptureDevice is running").release()); |
| 150 | 169 |
| 151 // Starts timer. | 170 // Starts timer. |
| 152 timer_.Start(FROM_HERE, | 171 timer_.Start(FROM_HERE, |
| 153 std::max(oracle_proxy_->min_capture_period(), | 172 std::max(oracle_proxy_->min_capture_period(), |
| 154 base::TimeDelta::FromMilliseconds( | 173 base::TimeDelta::FromMilliseconds(media:: |
| 155 VideoCaptureOracle::kMinTimerPollPeriodMillis)), | 174 VideoCaptureOracle::kMinTimerPollPeriodMillis)), |
| 156 base::Bind(&AuraWindowCaptureMachine::Capture, AsWeakPtr(), | 175 base::Bind(&AuraWindowCaptureMachine::Capture, AsWeakPtr(), |
| 157 false)); | 176 false)); |
| 158 | 177 |
| 159 return true; | 178 return true; |
| 160 } | 179 } |
| 161 | 180 |
| 162 void AuraWindowCaptureMachine::Stop(const base::Closure& callback) { | 181 void AuraWindowCaptureMachine::Stop(const base::Closure& callback) { |
| 182 // Stops the capture machine asynchronously. |
| 183 BrowserThread::PostTask( |
| 184 BrowserThread::UI, FROM_HERE, base::Bind( |
| 185 &AuraWindowCaptureMachine::InternalStop, |
| 186 base::Unretained(this), |
| 187 callback)); |
| 188 } |
| 189 |
| 190 void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) { |
| 163 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 191 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 164 power_save_blocker_.reset(); | 192 power_save_blocker_.reset(); |
| 165 | 193 |
| 166 // Stop observing compositor and window events. | 194 // Stop observing compositor and window events. |
| 167 if (desktop_window_) { | 195 if (desktop_window_) { |
| 168 aura::WindowTreeHost* window_host = desktop_window_->GetHost(); | 196 aura::WindowTreeHost* window_host = desktop_window_->GetHost(); |
| 169 // In the host destructor the compositor is destroyed before the window. | 197 // In the host destructor the compositor is destroyed before the window. |
| 170 if (window_host && window_host->compositor()) | 198 if (window_host && window_host->compositor()) |
| 171 window_host->compositor()->RemoveObserver(this); | 199 window_host->compositor()->RemoveObserver(this); |
| 172 desktop_window_->RemoveObserver(this); | 200 desktop_window_->RemoveObserver(this); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 } | 234 } |
| 207 | 235 |
| 208 void AuraWindowCaptureMachine::Capture(bool dirty) { | 236 void AuraWindowCaptureMachine::Capture(bool dirty) { |
| 209 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 237 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 210 | 238 |
| 211 // Do not capture if the desktop window is already destroyed. | 239 // Do not capture if the desktop window is already destroyed. |
| 212 if (!desktop_window_) | 240 if (!desktop_window_) |
| 213 return; | 241 return; |
| 214 | 242 |
| 215 scoped_refptr<media::VideoFrame> frame; | 243 scoped_refptr<media::VideoFrame> frame; |
| 216 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; | 244 media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; |
| 217 | 245 |
| 218 // TODO(miu): Need to fix this so the compositor is providing the presentation | 246 // TODO(miu): Need to fix this so the compositor is providing the presentation |
| 219 // timestamps and damage regions, to leverage the frame timestamp rewriting | 247 // timestamps and damage regions, to leverage the frame timestamp rewriting |
| 220 // logic. http://crbug.com/492839 | 248 // logic. http://crbug.com/492839 |
| 221 const base::TimeTicks start_time = base::TimeTicks::Now(); | 249 const base::TimeTicks start_time = base::TimeTicks::Now(); |
| 222 const VideoCaptureOracle::Event event = | 250 const media::VideoCaptureOracle::Event event = |
| 223 dirty ? VideoCaptureOracle::kCompositorUpdate | 251 dirty ? media::VideoCaptureOracle::kCompositorUpdate |
| 224 : VideoCaptureOracle::kTimerPoll; | 252 : media::VideoCaptureOracle::kTimerPoll; |
| 225 if (oracle_proxy_->ObserveEventAndDecideCapture( | 253 if (oracle_proxy_->ObserveEventAndDecideCapture( |
| 226 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { | 254 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { |
| 227 scoped_ptr<cc::CopyOutputRequest> request = | 255 scoped_ptr<cc::CopyOutputRequest> request = |
| 228 cc::CopyOutputRequest::CreateRequest( | 256 cc::CopyOutputRequest::CreateRequest( |
| 229 base::Bind(&AuraWindowCaptureMachine::DidCopyOutput, | 257 base::Bind(&AuraWindowCaptureMachine::DidCopyOutput, |
| 230 AsWeakPtr(), frame, start_time, capture_frame_cb)); | 258 AsWeakPtr(), frame, start_time, capture_frame_cb)); |
| 231 gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(), | 259 gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(), |
| 232 desktop_window_->bounds().height()); | 260 desktop_window_->bounds().height()); |
| 233 request->set_area(window_rect); | 261 request->set_area(window_rect); |
| 234 desktop_window_->layer()->RequestCopyOfOutput(request.Pass()); | 262 desktop_window_->layer()->RequestCopyOfOutput(request.Pass()); |
| 235 } | 263 } |
| 236 } | 264 } |
| 237 | 265 |
| 238 void AuraWindowCaptureMachine::DidCopyOutput( | 266 void AuraWindowCaptureMachine::DidCopyOutput( |
| 239 scoped_refptr<media::VideoFrame> video_frame, | 267 scoped_refptr<media::VideoFrame> video_frame, |
| 240 base::TimeTicks start_time, | 268 base::TimeTicks start_time, |
| 241 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 269 const CaptureFrameCallback& capture_frame_cb, |
| 242 scoped_ptr<cc::CopyOutputResult> result) { | 270 scoped_ptr<cc::CopyOutputResult> result) { |
| 243 static bool first_call = true; | 271 static bool first_call = true; |
| 244 | 272 |
| 245 bool succeeded = ProcessCopyOutputResponse( | 273 bool succeeded = ProcessCopyOutputResponse( |
| 246 video_frame, start_time, capture_frame_cb, result.Pass()); | 274 video_frame, start_time, capture_frame_cb, result.Pass()); |
| 247 | 275 |
| 248 base::TimeDelta capture_time = base::TimeTicks::Now() - start_time; | 276 base::TimeDelta capture_time = base::TimeTicks::Now() - start_time; |
| 249 | 277 |
| 250 // The two UMA_ blocks must be put in its own scope since it creates a static | 278 // The two UMA_ blocks must be put in its own scope since it creates a static |
| 251 // variable which expected constant histogram name. | 279 // variable which expected constant histogram name. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 264 IncrementDesktopCaptureCounter(succeeded | 292 IncrementDesktopCaptureCounter(succeeded |
| 265 ? FIRST_WINDOW_CAPTURE_SUCCEEDED | 293 ? FIRST_WINDOW_CAPTURE_SUCCEEDED |
| 266 : FIRST_WINDOW_CAPTURE_FAILED); | 294 : FIRST_WINDOW_CAPTURE_FAILED); |
| 267 } | 295 } |
| 268 } | 296 } |
| 269 } | 297 } |
| 270 | 298 |
| 271 bool AuraWindowCaptureMachine::ProcessCopyOutputResponse( | 299 bool AuraWindowCaptureMachine::ProcessCopyOutputResponse( |
| 272 scoped_refptr<media::VideoFrame> video_frame, | 300 scoped_refptr<media::VideoFrame> video_frame, |
| 273 base::TimeTicks start_time, | 301 base::TimeTicks start_time, |
| 274 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | 302 const CaptureFrameCallback& capture_frame_cb, |
| 275 scoped_ptr<cc::CopyOutputResult> result) { | 303 scoped_ptr<cc::CopyOutputResult> result) { |
| 276 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 304 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 277 | 305 |
| 278 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_window_) | 306 if (result->IsEmpty() || result->size().IsEmpty() || !desktop_window_) |
| 279 return false; | 307 return false; |
| 280 | 308 |
| 281 if (capture_params_.requested_format.pixel_format == | 309 if (capture_params_.requested_format.pixel_format == |
| 282 media::PIXEL_FORMAT_TEXTURE) { | 310 media::PIXEL_FORMAT_TEXTURE) { |
| 283 DCHECK(!video_frame.get()); | 311 DCHECK(!video_frame.get()); |
| 284 cc::TextureMailbox texture_mailbox; | 312 cc::TextureMailbox texture_mailbox; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 | 477 |
| 450 void AuraWindowCaptureMachine::OnCompositingEnded( | 478 void AuraWindowCaptureMachine::OnCompositingEnded( |
| 451 ui::Compositor* compositor) { | 479 ui::Compositor* compositor) { |
| 452 // TODO(miu): The CopyOutputRequest should be made earlier, at WillCommit(). | 480 // TODO(miu): The CopyOutputRequest should be made earlier, at WillCommit(). |
| 453 // http://crbug.com/492839 | 481 // http://crbug.com/492839 |
| 454 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 482 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| 455 &AuraWindowCaptureMachine::Capture, AsWeakPtr(), true)); | 483 &AuraWindowCaptureMachine::Capture, AsWeakPtr(), true)); |
| 456 } | 484 } |
| 457 | 485 |
| 458 } // namespace content | 486 } // namespace content |
| OLD | NEW |