| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // Implementation notes: This needs to work on a variety of hardware | 5 // Implementation notes: This needs to work on a variety of hardware |
| 6 // configurations where the speed of the CPU and GPU greatly affect overall | 6 // configurations where the speed of the CPU and GPU greatly affect overall |
| 7 // performance. Therefore, the process of capturing has been split up into a | 7 // performance. Therefore, the process of capturing has been split up into a |
| 8 // pipeline of three stages. Each stage executes on its own thread: | 8 // pipeline of three stages. Each stage executes on its own thread: |
| 9 // | 9 // |
| 10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing | 10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 #include "base/callback_forward.h" | 49 #include "base/callback_forward.h" |
| 50 #include "base/debug/trace_event.h" | 50 #include "base/debug/trace_event.h" |
| 51 #include "base/logging.h" | 51 #include "base/logging.h" |
| 52 #include "base/memory/scoped_ptr.h" | 52 #include "base/memory/scoped_ptr.h" |
| 53 #include "base/metrics/histogram.h" | 53 #include "base/metrics/histogram.h" |
| 54 #include "base/stringprintf.h" | 54 #include "base/stringprintf.h" |
| 55 #include "base/synchronization/lock.h" | 55 #include "base/synchronization/lock.h" |
| 56 #include "base/threading/thread.h" | 56 #include "base/threading/thread.h" |
| 57 #include "base/time.h" | 57 #include "base/time.h" |
| 58 #include "content/browser/renderer_host/media/web_contents_capture_util.h" | 58 #include "content/browser/renderer_host/media/web_contents_capture_util.h" |
| 59 #include "content/browser/web_contents/web_contents_impl.h" |
| 59 #include "content/public/browser/browser_thread.h" | 60 #include "content/public/browser/browser_thread.h" |
| 60 #include "content/public/browser/render_process_host.h" | 61 #include "content/public/browser/render_process_host.h" |
| 61 #include "content/public/browser/render_view_host.h" | 62 #include "content/public/browser/render_view_host.h" |
| 62 #include "content/public/browser/render_widget_host_view.h" | 63 #include "content/public/browser/render_widget_host_view.h" |
| 63 #include "content/public/browser/web_contents.h" | 64 #include "content/public/browser/web_contents.h" |
| 64 #include "content/public/browser/web_contents_observer.h" | 65 #include "content/public/browser/web_contents_observer.h" |
| 65 #include "media/base/bind_to_loop.h" | 66 #include "media/base/bind_to_loop.h" |
| 66 #include "media/video/capture/video_capture_types.h" | 67 #include "media/video/capture/video_capture_types.h" |
| 67 #include "skia/ext/image_operations.h" | 68 #include "skia/ext/image_operations.h" |
| 68 #include "skia/ext/platform_canvas.h" | 69 #include "skia/ext/platform_canvas.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 // This is used for unit testing. | 156 // This is used for unit testing. |
| 156 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); | 157 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); |
| 157 | 158 |
| 158 // Starts the copy from the backing store. Must be run on the UI | 159 // Starts the copy from the backing store. Must be run on the UI |
| 159 // BrowserThread. |done_cb| is invoked with result status. When successful | 160 // BrowserThread. |done_cb| is invoked with result status. When successful |
| 160 // (OK), the bitmap of the capture is transferred to the callback along with | 161 // (OK), the bitmap of the capture is transferred to the callback along with |
| 161 // the timestamp at which the capture was completed. | 162 // the timestamp at which the capture was completed. |
| 162 void StartCopy(int frame_number, int desired_width, int desired_height, | 163 void StartCopy(int frame_number, int desired_width, int desired_height, |
| 163 const DoneCB& done_cb); | 164 const DoneCB& done_cb); |
| 164 | 165 |
| 166 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { |
| 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 168 fullscreen_widget_id_ = routing_id; |
| 169 } |
| 170 |
| 171 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { |
| 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 173 DCHECK_EQ(fullscreen_widget_id_, routing_id); |
| 174 fullscreen_widget_id_ = MSG_ROUTING_NONE; |
| 175 } |
| 176 |
| 165 private: | 177 private: |
| 166 void LookUpAndObserveWebContents(); | 178 void LookUpAndObserveWebContents(); |
| 167 | 179 |
| 168 void CopyFromBackingStoreComplete(int frame_number, | 180 void CopyFromBackingStoreComplete(int frame_number, |
| 169 scoped_ptr<skia::PlatformBitmap> capture, | 181 scoped_ptr<skia::PlatformBitmap> capture, |
| 170 const DoneCB& done_cb, bool success); | 182 const DoneCB& done_cb, bool success); |
| 171 | 183 |
| 172 // The "starting point" to find the capture source. | 184 // The "starting point" to find the capture source. |
| 173 const int render_process_id_; | 185 const int render_process_id_; |
| 174 const int render_view_id_; | 186 const int render_view_id_; |
| 175 | 187 |
| 188 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE |
| 189 // otherwise. |
| 190 int fullscreen_widget_id_; |
| 191 |
| 176 // Last known RenderView size. | 192 // Last known RenderView size. |
| 177 gfx::Size last_view_size_; | 193 gfx::Size last_view_size_; |
| 178 | 194 |
| 179 // If the following is NULL (normal behavior), the implementation should | 195 // If the following is NULL (normal behavior), the implementation should |
| 180 // access RenderWidgetHost via web_contents(). | 196 // access RenderWidgetHost via web_contents(). |
| 181 RenderWidgetHost* rwh_for_testing_; | 197 RenderWidgetHost* rwh_for_testing_; |
| 182 | 198 |
| 183 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); | 199 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); |
| 184 }; | 200 }; |
| 185 | 201 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 base::Time last_frame_rate_log_time_; | 281 base::Time last_frame_rate_log_time_; |
| 266 int count_frames_rendered_; | 282 int count_frames_rendered_; |
| 267 int last_frame_number_; | 283 int last_frame_number_; |
| 268 | 284 |
| 269 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); | 285 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); |
| 270 }; | 286 }; |
| 271 | 287 |
| 272 BackingStoreCopier::BackingStoreCopier(int render_process_id, | 288 BackingStoreCopier::BackingStoreCopier(int render_process_id, |
| 273 int render_view_id) | 289 int render_view_id) |
| 274 : render_process_id_(render_process_id), render_view_id_(render_view_id), | 290 : render_process_id_(render_process_id), render_view_id_(render_view_id), |
| 275 rwh_for_testing_(NULL) {} | 291 fullscreen_widget_id_(MSG_ROUTING_NONE), rwh_for_testing_(NULL) {} |
| 276 | 292 |
| 277 void BackingStoreCopier::LookUpAndObserveWebContents() { | 293 void BackingStoreCopier::LookUpAndObserveWebContents() { |
| 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 279 | 295 |
| 280 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. | 296 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. |
| 281 // If successful, begin observing the WebContents instance. If unsuccessful, | 297 // If successful, begin observing the WebContents instance. If unsuccessful, |
| 282 // stop observing and post an error. | 298 // stop observing and post an error. |
| 283 // | 299 // |
| 284 // Why this can be unsuccessful: The request for mirroring originates in a | 300 // Why this can be unsuccessful: The request for mirroring originates in a |
| 285 // render process, and this request is based on the current RenderView | 301 // render process, and this request is based on the current RenderView |
| 286 // associated with a tab. However, by the time we get up-and-running here, | 302 // associated with a tab. However, by the time we get up-and-running here, |
| 287 // there have been multiple back-and-forth IPCs between processes, as well as | 303 // there have been multiple back-and-forth IPCs between processes, as well as |
| 288 // a bit of indirection across threads. It's easily possible that, in the | 304 // a bit of indirection across threads. It's easily possible that, in the |
| 289 // meantime, the original RenderView may have gone away. | 305 // meantime, the original RenderView may have gone away. |
| 290 RenderViewHost* const rvh = | 306 RenderViewHost* const rvh = |
| 291 RenderViewHost::FromID(render_process_id_, render_view_id_); | 307 RenderViewHost::FromID(render_process_id_, render_view_id_); |
| 292 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" | 308 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" |
| 293 << render_process_id_ << ", " << render_view_id_ | 309 << render_process_id_ << ", " << render_view_id_ |
| 294 << ") returned NULL."; | 310 << ") returned NULL."; |
| 295 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); | 311 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); |
| 296 DVLOG_IF(1, !web_contents()) | 312 DVLOG_IF(1, !web_contents()) |
| 297 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; | 313 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; |
| 314 |
| 315 if (fullscreen_widget_id_ == MSG_ROUTING_NONE && web_contents()) { |
| 316 fullscreen_widget_id_ = static_cast<WebContentsImpl*>(web_contents())-> |
| 317 GetFullscreenWidgetRoutingID(); |
| 318 } |
| 298 } | 319 } |
| 299 | 320 |
| 300 void BackingStoreCopier::SetRenderWidgetHostForTesting( | 321 void BackingStoreCopier::SetRenderWidgetHostForTesting( |
| 301 RenderWidgetHost* override) { | 322 RenderWidgetHost* override) { |
| 302 rwh_for_testing_ = override; | 323 rwh_for_testing_ = override; |
| 303 } | 324 } |
| 304 | 325 |
| 305 void BackingStoreCopier::StartCopy(int frame_number, | 326 void BackingStoreCopier::StartCopy(int frame_number, |
| 306 int desired_width, int desired_height, | 327 int desired_width, int desired_height, |
| 307 const DoneCB& done_cb) { | 328 const DoneCB& done_cb) { |
| 308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 309 | 330 |
| 310 TRACE_EVENT_ASYNC_BEGIN1("mirroring", "Capture", this, | 331 TRACE_EVENT_ASYNC_BEGIN1("mirroring", "Capture", this, |
| 311 "frame_number", frame_number); | 332 "frame_number", frame_number); |
| 312 | 333 |
| 313 RenderWidgetHost* rwh; | 334 RenderWidgetHost* rwh; |
| 314 if (rwh_for_testing_) { | 335 if (rwh_for_testing_) { |
| 315 rwh = rwh_for_testing_; | 336 rwh = rwh_for_testing_; |
| 316 } else { | 337 } else { |
| 317 if (!web_contents()) { // No source yet. | 338 if (!web_contents()) { // No source yet. |
| 318 LookUpAndObserveWebContents(); | 339 LookUpAndObserveWebContents(); |
| 319 if (!web_contents()) { // No source ever. | 340 if (!web_contents()) { // No source ever. |
| 320 done_cb.Run(NO_SOURCE, | 341 done_cb.Run(NO_SOURCE, |
| 321 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); | 342 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); |
| 322 return; | 343 return; |
| 323 } | 344 } |
| 324 } | 345 } |
| 325 rwh = web_contents()->GetRenderViewHost(); | 346 |
| 347 if (fullscreen_widget_id_ != MSG_ROUTING_NONE) { |
| 348 RenderProcessHost* process = web_contents()->GetRenderProcessHost(); |
| 349 rwh = process ? process->GetRenderWidgetHostByID(fullscreen_widget_id_) |
| 350 : NULL; |
| 351 } else { |
| 352 rwh = web_contents()->GetRenderViewHost(); |
| 353 } |
| 354 |
| 326 if (!rwh) { | 355 if (!rwh) { |
| 327 // Transient failure state (e.g., a RenderView is being replaced). | 356 // Transient failure state (e.g., a RenderView is being replaced). |
| 328 done_cb.Run(TRANSIENT_ERROR, | 357 done_cb.Run(TRANSIENT_ERROR, |
| 329 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); | 358 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); |
| 330 return; | 359 return; |
| 331 } | 360 } |
| 332 } | 361 } |
| 333 | 362 |
| 334 gfx::Size fitted_size; | 363 gfx::Size fitted_size; |
| 335 if (RenderWidgetHostView* const view = rwh->GetView()) { | 364 if (RenderWidgetHostView* const view = rwh->GetView()) { |
| (...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1066 capturer_->SetConsumer(NULL); | 1095 capturer_->SetConsumer(NULL); |
| 1067 capturer_->DeAllocate(); | 1096 capturer_->DeAllocate(); |
| 1068 } | 1097 } |
| 1069 | 1098 |
| 1070 const media::VideoCaptureDevice::Name& | 1099 const media::VideoCaptureDevice::Name& |
| 1071 WebContentsVideoCaptureDevice::device_name() { | 1100 WebContentsVideoCaptureDevice::device_name() { |
| 1072 return device_name_; | 1101 return device_name_; |
| 1073 } | 1102 } |
| 1074 | 1103 |
| 1075 } // namespace content | 1104 } // namespace content |
| OLD | NEW |