| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 #include "content/public/browser/web_contents_observer.h" | 66 #include "content/public/browser/web_contents_observer.h" |
| 67 #include "media/base/bind_to_loop.h" | 67 #include "media/base/bind_to_loop.h" |
| 68 #include "media/base/video_frame.h" | 68 #include "media/base/video_frame.h" |
| 69 #include "media/video/capture/video_capture_types.h" | 69 #include "media/video/capture/video_capture_types.h" |
| 70 #include "skia/ext/image_operations.h" | 70 #include "skia/ext/image_operations.h" |
| 71 #include "third_party/skia/include/core/SkBitmap.h" | 71 #include "third_party/skia/include/core/SkBitmap.h" |
| 72 #include "third_party/skia/include/core/SkColor.h" | 72 #include "third_party/skia/include/core/SkColor.h" |
| 73 #include "ui/gfx/rect.h" | 73 #include "ui/gfx/rect.h" |
| 74 #include "ui/gfx/skia_util.h" | 74 #include "ui/gfx/skia_util.h" |
| 75 | 75 |
| 76 // Used to self-trampoline invocation of methods to the approprate thread. This | 76 // Used to self-trampoline invocation of methods to the appropriate thread. This |
| 77 // should be used sparingly, only when it's not clear which thread is invoking a | 77 // should be used sparingly, only when it's not clear which thread is invoking a |
| 78 // method. | 78 // method. |
| 79 #define ENSURE_INVOKED_ON_THREAD(thread, ...) { \ | 79 #define ENSURE_INVOKED_ON_THREAD(thread, ...) { \ |
| 80 DCHECK(thread.IsRunning()); \ | 80 DCHECK(thread.IsRunning()); \ |
| 81 if (MessageLoop::current() != thread.message_loop()) { \ | 81 if (MessageLoop::current() != thread.message_loop()) { \ |
| 82 thread.message_loop()->PostTask(FROM_HERE, base::Bind(__VA_ARGS__)); \ | 82 thread.message_loop()->PostTask(FROM_HERE, base::Bind(__VA_ARGS__)); \ |
| 83 return; \ | 83 return; \ |
| 84 } \ | 84 } \ |
| 85 } | 85 } |
| 86 | 86 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 } | 139 } |
| 140 | 140 |
| 141 // Keeps track of the RenderView to be sourced, and executes copying of the | 141 // Keeps track of the RenderView to be sourced, and executes copying of the |
| 142 // backing store on the UI BrowserThread. | 142 // backing store on the UI BrowserThread. |
| 143 class BackingStoreCopier : public WebContentsObserver { | 143 class BackingStoreCopier : public WebContentsObserver { |
| 144 public: | 144 public: |
| 145 BackingStoreCopier(int render_process_id, int render_view_id); | 145 BackingStoreCopier(int render_process_id, int render_view_id); |
| 146 | 146 |
| 147 virtual ~BackingStoreCopier(); | 147 virtual ~BackingStoreCopier(); |
| 148 | 148 |
| 149 // If non-NULL, use the given |override| to access the backing store. | |
| 150 // This is used for unit testing. | |
| 151 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); | |
| 152 | |
| 153 // Starts the copy from the backing store. Must be run on the UI | 149 // Starts the copy from the backing store. Must be run on the UI |
| 154 // BrowserThread. Resulting frame is conveyed back to |consumer|. | 150 // BrowserThread. Resulting frame is conveyed back to |consumer|. |
| 155 void StartCopy(const scoped_refptr<CaptureMachine>& consumer, | 151 void StartCopy(const scoped_refptr<CaptureMachine>& consumer, |
| 156 int frame_number, | 152 int frame_number, |
| 157 int desired_width, | 153 int desired_width, |
| 158 int desired_height); | 154 int desired_height); |
| 159 | 155 |
| 160 // Stops observing an existing WebContents instance, if any. This must be | 156 // Stops observing an existing WebContents instance, if any. This must be |
| 161 // called before BackingStoreCopier is destroyed. Must be run on the UI | 157 // called before BackingStoreCopier is destroyed. Must be run on the UI |
| 162 // BrowserThread. | 158 // BrowserThread. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 const int render_process_id_; | 194 const int render_process_id_; |
| 199 const int render_view_id_; | 195 const int render_view_id_; |
| 200 | 196 |
| 201 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE | 197 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE |
| 202 // otherwise. | 198 // otherwise. |
| 203 int fullscreen_widget_id_; | 199 int fullscreen_widget_id_; |
| 204 | 200 |
| 205 // Last known RenderView size. | 201 // Last known RenderView size. |
| 206 gfx::Size last_view_size_; | 202 gfx::Size last_view_size_; |
| 207 | 203 |
| 208 // If the following is NULL (normal behavior), the implementation should | |
| 209 // access RenderWidgetHost via web_contents(). | |
| 210 RenderWidgetHost* rwh_for_testing_; | |
| 211 | |
| 212 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); | 204 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); |
| 213 }; | 205 }; |
| 214 | 206 |
| 215 // Renders captures (from the backing store) into video frame buffers on a | 207 // Renders captures (from the backing store) into video frame buffers on a |
| 216 // separate thread. Manages use of internally-owned video frame buffers. | 208 // separate thread. Manages use of internally-owned video frame buffers. |
| 217 class VideoFrameRenderer { | 209 class VideoFrameRenderer { |
| 218 public: | 210 public: |
| 219 typedef base::Callback<void(const SkBitmap*)> DoneCB; | 211 typedef base::Callback<void(const SkBitmap*)> DoneCB; |
| 220 | 212 |
| 221 VideoFrameRenderer(); | 213 VideoFrameRenderer(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // deliver stage) whenever verbose logging is turned on. | 304 // deliver stage) whenever verbose logging is turned on. |
| 313 base::Time last_frame_rate_log_time_; | 305 base::Time last_frame_rate_log_time_; |
| 314 int count_frames_rendered_; | 306 int count_frames_rendered_; |
| 315 int last_frame_number_; | 307 int last_frame_number_; |
| 316 | 308 |
| 317 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); | 309 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); |
| 318 }; | 310 }; |
| 319 | 311 |
| 320 BackingStoreCopier::BackingStoreCopier(int render_process_id, | 312 BackingStoreCopier::BackingStoreCopier(int render_process_id, |
| 321 int render_view_id) | 313 int render_view_id) |
| 322 : render_process_id_(render_process_id), render_view_id_(render_view_id), | 314 : render_process_id_(render_process_id), |
| 323 fullscreen_widget_id_(MSG_ROUTING_NONE), rwh_for_testing_(NULL) {} | 315 render_view_id_(render_view_id), |
| 316 fullscreen_widget_id_(MSG_ROUTING_NONE) {} |
| 324 | 317 |
| 325 BackingStoreCopier::~BackingStoreCopier() { | 318 BackingStoreCopier::~BackingStoreCopier() { |
| 326 DCHECK(!web_contents()); | 319 DCHECK(!web_contents()); |
| 327 } | 320 } |
| 328 | 321 |
| 329 void BackingStoreCopier::StopObservingWebContents() { | 322 void BackingStoreCopier::StopObservingWebContents() { |
| 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 331 | 324 |
| 332 if (web_contents()) { | 325 if (web_contents()) { |
| 333 web_contents()->DecrementCapturerCount(); | 326 web_contents()->DecrementCapturerCount(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 362 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); | 355 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); |
| 363 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents()); | 356 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents()); |
| 364 if (contents) { | 357 if (contents) { |
| 365 contents->IncrementCapturerCount(); | 358 contents->IncrementCapturerCount(); |
| 366 fullscreen_widget_id_ = contents->GetFullscreenWidgetRoutingID(); | 359 fullscreen_widget_id_ = contents->GetFullscreenWidgetRoutingID(); |
| 367 } else { | 360 } else { |
| 368 DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; | 361 DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; |
| 369 } | 362 } |
| 370 } | 363 } |
| 371 | 364 |
| 372 void BackingStoreCopier::SetRenderWidgetHostForTesting( | |
| 373 RenderWidgetHost* override) { | |
| 374 rwh_for_testing_ = override; | |
| 375 } | |
| 376 | |
| 377 VideoFrameRenderer::VideoFrameRenderer() | 365 VideoFrameRenderer::VideoFrameRenderer() |
| 378 : render_thread_("WebContentsVideo_RenderThread") { | 366 : render_thread_("WebContentsVideo_RenderThread") { |
| 379 output_[0].in_use = false; | 367 output_[0].in_use = false; |
| 380 output_[1].in_use = false; | 368 output_[1].in_use = false; |
| 381 render_thread_.Start(); | 369 render_thread_.Start(); |
| 382 } | 370 } |
| 383 | 371 |
| 384 void VideoFrameRenderer::Render(int frame_number, | 372 void VideoFrameRenderer::Render(int frame_number, |
| 385 const SkBitmap& capture, | 373 const SkBitmap& capture, |
| 386 int frame_width, int frame_height, | 374 int frame_width, int frame_height, |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 // top of this file). It times the start of successive captures and | 652 // top of this file). It times the start of successive captures and |
| 665 // facilitates the processing of each through the stages of the pipeline. | 653 // facilitates the processing of each through the stages of the pipeline. |
| 666 class CaptureMachine | 654 class CaptureMachine |
| 667 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> { | 655 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> { |
| 668 public: | 656 public: |
| 669 enum SnapshotError { | 657 enum SnapshotError { |
| 670 NO_SOURCE, | 658 NO_SOURCE, |
| 671 TRANSIENT_ERROR | 659 TRANSIENT_ERROR |
| 672 }; | 660 }; |
| 673 | 661 |
| 674 CaptureMachine(int render_process_id, int render_view_id); | 662 // |destroy_cb| will be invoked after CaptureMachine is fully destroyed, |
| 675 | 663 // to synchronize tear-down. |
| 676 // Sets the capture source to the given |override| for unit testing. | 664 CaptureMachine(int render_process_id, |
| 677 // Also, |destroy_cb| will be invoked after CaptureMachine is fully destroyed | 665 int render_view_id, |
| 678 // (to synchronize tear-down). | 666 const base::Closure& destroy_cb); |
| 679 void InitializeForTesting(RenderWidgetHost* override, | |
| 680 const base::Closure& destroy_cb); | |
| 681 | 667 |
| 682 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove | 668 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove |
| 683 // the reference to the consumer; then, once this method returns, | 669 // the reference to the consumer; then, once this method returns, |
| 684 // CaptureMachine will no longer invoke callbacks on the old consumer from any | 670 // CaptureMachine will no longer invoke callbacks on the old consumer from any |
| 685 // thread. | 671 // thread. |
| 686 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer); | 672 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer); |
| 687 | 673 |
| 688 // Asynchronous requests to change CaptureMachine state. | 674 // Asynchronous requests to change CaptureMachine state. |
| 689 void Allocate(int width, int height, int frame_rate); | 675 void Allocate(int width, int height, int frame_rate); |
| 690 void Start(); | 676 void Start(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 // The three pipeline stages. | 757 // The three pipeline stages. |
| 772 BackingStoreCopier copier_; | 758 BackingStoreCopier copier_; |
| 773 VideoFrameRenderer renderer_; | 759 VideoFrameRenderer renderer_; |
| 774 VideoFrameDeliverer deliverer_; | 760 VideoFrameDeliverer deliverer_; |
| 775 | 761 |
| 776 base::Closure destroy_cb_; // Invoked once CaptureMachine is destroyed. | 762 base::Closure destroy_cb_; // Invoked once CaptureMachine is destroyed. |
| 777 | 763 |
| 778 DISALLOW_COPY_AND_ASSIGN(CaptureMachine); | 764 DISALLOW_COPY_AND_ASSIGN(CaptureMachine); |
| 779 }; | 765 }; |
| 780 | 766 |
| 781 CaptureMachine::CaptureMachine(int render_process_id, int render_view_id) | 767 CaptureMachine::CaptureMachine(int render_process_id, |
| 768 int render_view_id, |
| 769 const base::Closure& destroy_cb) |
| 782 : manager_thread_("WebContentsVideo_ManagerThread"), | 770 : manager_thread_("WebContentsVideo_ManagerThread"), |
| 783 state_(kIdle), | 771 state_(kIdle), |
| 784 is_snapshotting_(false), | 772 is_snapshotting_(false), |
| 785 num_renders_pending_(0), | 773 num_renders_pending_(0), |
| 786 copier_(render_process_id, render_view_id), | 774 copier_(render_process_id, render_view_id), |
| 787 deliverer_(&consumer_) { | 775 deliverer_(&consumer_), |
| 776 destroy_cb_(destroy_cb) { |
| 788 manager_thread_.Start(); | 777 manager_thread_.Start(); |
| 789 } | 778 } |
| 790 | 779 |
| 791 void CaptureMachine::InitializeForTesting(RenderWidgetHost* override, | |
| 792 const base::Closure& destroy_cb) { | |
| 793 copier_.SetRenderWidgetHostForTesting(override); | |
| 794 destroy_cb_ = destroy_cb; | |
| 795 } | |
| 796 | |
| 797 void CaptureMachine::SetConsumer( | 780 void CaptureMachine::SetConsumer( |
| 798 media::VideoCaptureDevice::EventHandler* consumer) { | 781 media::VideoCaptureDevice::EventHandler* consumer) { |
| 799 consumer_.SetConsumer(consumer); | 782 consumer_.SetConsumer(consumer); |
| 800 } | 783 } |
| 801 | 784 |
| 802 void CaptureMachine::Allocate(int width, int height, int frame_rate) { | 785 void CaptureMachine::Allocate(int width, int height, int frame_rate) { |
| 803 ENSURE_INVOKED_ON_THREAD(manager_thread_, | 786 ENSURE_INVOKED_ON_THREAD(manager_thread_, |
| 804 &CaptureMachine::Allocate, this, | 787 &CaptureMachine::Allocate, this, |
| 805 width, height, frame_rate); | 788 width, height, frame_rate); |
| 806 | 789 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 // another thread. | 884 // another thread. |
| 902 BrowserThread::PostBlockingPoolTask( | 885 BrowserThread::PostBlockingPoolTask( |
| 903 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x)); | 886 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x)); |
| 904 } | 887 } |
| 905 | 888 |
| 906 // static | 889 // static |
| 907 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) { | 890 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) { |
| 908 const base::Closure run_after_delete = x->destroy_cb_; | 891 const base::Closure run_after_delete = x->destroy_cb_; |
| 909 // Note: Thread joins are about to happen here (in ~CaptureThread()). | 892 // Note: Thread joins are about to happen here (in ~CaptureThread()). |
| 910 delete x; | 893 delete x; |
| 911 if (!run_after_delete.is_null()) { | 894 if (!run_after_delete.is_null()) |
| 912 run_after_delete.Run(); | 895 run_after_delete.Run(); |
| 913 } | |
| 914 } | 896 } |
| 915 | 897 |
| 916 void CaptureMachine::TransitionStateTo(State next_state) { | 898 void CaptureMachine::TransitionStateTo(State next_state) { |
| 917 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current()); | 899 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current()); |
| 918 | 900 |
| 919 #ifndef NDEBUG | 901 #ifndef NDEBUG |
| 920 static const char* kStateNames[] = { | 902 static const char* kStateNames[] = { |
| 921 "Idle", "Allocated", "Capturing", "Error", "Destroyed" | 903 "Idle", "Allocated", "Capturing", "Error", "Destroyed" |
| 922 }; | 904 }; |
| 923 DVLOG(1) << "State change: " << kStateNames[state_] | 905 DVLOG(1) << "State change: " << kStateNames[state_] |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1094 copier_.StopObservingWebContents(); | 1076 copier_.StopObservingWebContents(); |
| 1095 } | 1077 } |
| 1096 | 1078 |
| 1097 void BackingStoreCopier::StartCopy( | 1079 void BackingStoreCopier::StartCopy( |
| 1098 const scoped_refptr<CaptureMachine>& consumer, | 1080 const scoped_refptr<CaptureMachine>& consumer, |
| 1099 int frame_number, | 1081 int frame_number, |
| 1100 int desired_width, | 1082 int desired_width, |
| 1101 int desired_height) { | 1083 int desired_height) { |
| 1102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1084 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1103 | 1085 |
| 1104 RenderWidgetHost* rwh; | 1086 if (!web_contents()) { // No source yet. |
| 1105 if (rwh_for_testing_) { | 1087 LookUpAndObserveWebContents(); |
| 1106 rwh = rwh_for_testing_; | 1088 if (!web_contents()) { // No source ever. |
| 1107 } else { | 1089 consumer->OnSnapshotFailed(CaptureMachine::NO_SOURCE, frame_number); |
| 1108 if (!web_contents()) { // No source yet. | |
| 1109 LookUpAndObserveWebContents(); | |
| 1110 if (!web_contents()) { // No source ever. | |
| 1111 consumer->OnSnapshotFailed(CaptureMachine::NO_SOURCE, frame_number); | |
| 1112 return; | |
| 1113 } | |
| 1114 } | |
| 1115 | |
| 1116 if (fullscreen_widget_id_ != MSG_ROUTING_NONE) { | |
| 1117 RenderProcessHost* process = web_contents()->GetRenderProcessHost(); | |
| 1118 rwh = process ? process->GetRenderWidgetHostByID(fullscreen_widget_id_) | |
| 1119 : NULL; | |
| 1120 } else { | |
| 1121 rwh = web_contents()->GetRenderViewHost(); | |
| 1122 } | |
| 1123 | |
| 1124 if (!rwh) { | |
| 1125 // Transient failure state (e.g., a RenderView is being replaced). | |
| 1126 consumer->OnSnapshotFailed(CaptureMachine::TRANSIENT_ERROR, frame_number); | |
| 1127 return; | 1090 return; |
| 1128 } | 1091 } |
| 1129 } | 1092 } |
| 1130 | 1093 |
| 1094 RenderWidgetHost* rwh; |
| 1095 if (fullscreen_widget_id_ != MSG_ROUTING_NONE) { |
| 1096 RenderProcessHost* process = web_contents()->GetRenderProcessHost(); |
| 1097 rwh = process ? process->GetRenderWidgetHostByID(fullscreen_widget_id_) |
| 1098 : NULL; |
| 1099 } else { |
| 1100 rwh = web_contents()->GetRenderViewHost(); |
| 1101 } |
| 1102 |
| 1103 if (!rwh) { |
| 1104 // Transient failure state (e.g., a RenderView is being replaced). |
| 1105 consumer->OnSnapshotFailed(CaptureMachine::TRANSIENT_ERROR, frame_number); |
| 1106 return; |
| 1107 } |
| 1108 |
| 1131 RenderWidgetHostViewPort* view = | 1109 RenderWidgetHostViewPort* view = |
| 1132 RenderWidgetHostViewPort::FromRWHV(rwh->GetView()); | 1110 RenderWidgetHostViewPort::FromRWHV(rwh->GetView()); |
| 1133 | 1111 |
| 1134 gfx::Size fitted_size; | 1112 gfx::Size fitted_size; |
| 1135 if (view) { | 1113 if (view) { |
| 1136 gfx::Size view_size = view->GetViewBounds().size(); | 1114 gfx::Size view_size = view->GetViewBounds().size(); |
| 1137 if (!view_size.IsEmpty()) { | 1115 if (!view_size.IsEmpty()) { |
| 1138 CalculateFittedSize(view_size.width(), view_size.height(), | 1116 CalculateFittedSize(view_size.width(), view_size.height(), |
| 1139 desired_width, desired_height, | 1117 desired_width, desired_height, |
| 1140 &fitted_size); | 1118 &fitted_size); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 } else { | 1199 } else { |
| 1222 // Capture can fail due to transient issues, so just skip this frame. | 1200 // Capture can fail due to transient issues, so just skip this frame. |
| 1223 DVLOG(1) << "CopyFromBackingStoreToVideoFrame failure; skipping frame."; | 1201 DVLOG(1) << "CopyFromBackingStoreToVideoFrame failure; skipping frame."; |
| 1224 consumer->OnSnapshotFailed( | 1202 consumer->OnSnapshotFailed( |
| 1225 CaptureMachine::TRANSIENT_ERROR, frame_number); | 1203 CaptureMachine::TRANSIENT_ERROR, frame_number); |
| 1226 } | 1204 } |
| 1227 } | 1205 } |
| 1228 | 1206 |
| 1229 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( | 1207 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( |
| 1230 const media::VideoCaptureDevice::Name& name, | 1208 const media::VideoCaptureDevice::Name& name, |
| 1231 int render_process_id, int render_view_id) | 1209 int render_process_id, |
| 1210 int render_view_id, |
| 1211 const base::Closure& destroy_cb) |
| 1232 : device_name_(name), | 1212 : device_name_(name), |
| 1233 capturer_(new CaptureMachine(render_process_id, render_view_id)) {} | 1213 capturer_(new CaptureMachine(render_process_id, render_view_id, |
| 1234 | 1214 destroy_cb)) {} |
| 1235 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( | |
| 1236 RenderWidgetHost* test_source, const base::Closure& destroy_cb) | |
| 1237 : capturer_(new CaptureMachine(-1, -1)) { | |
| 1238 device_name_.device_name = "WebContentsForTesting"; | |
| 1239 device_name_.unique_id = "-1:-1"; | |
| 1240 capturer_->InitializeForTesting(test_source, destroy_cb); | |
| 1241 } | |
| 1242 | 1215 |
| 1243 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { | 1216 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { |
| 1244 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; | 1217 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; |
| 1245 } | 1218 } |
| 1246 | 1219 |
| 1247 // static | 1220 // static |
| 1248 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( | 1221 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( |
| 1249 const std::string& device_id) { | 1222 const std::string& device_id, |
| 1223 const base::Closure& destroy_cb) { |
| 1250 // Parse device_id into render_process_id and render_view_id. | 1224 // Parse device_id into render_process_id and render_view_id. |
| 1251 int render_process_id = -1; | 1225 int render_process_id = -1; |
| 1252 int render_view_id = -1; | 1226 int render_view_id = -1; |
| 1253 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(device_id, | 1227 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(device_id, |
| 1254 &render_process_id, | 1228 &render_process_id, |
| 1255 &render_view_id)) | 1229 &render_view_id)) |
| 1256 return NULL; | 1230 return NULL; |
| 1257 | 1231 |
| 1258 media::VideoCaptureDevice::Name name; | 1232 media::VideoCaptureDevice::Name name; |
| 1259 base::SStringPrintf(&name.device_name, | 1233 base::SStringPrintf(&name.device_name, |
| 1260 "WebContents[%.*s]", | 1234 "WebContents[%.*s]", |
| 1261 static_cast<int>(device_id.size()), device_id.data()); | 1235 static_cast<int>(device_id.size()), device_id.data()); |
| 1262 name.unique_id = device_id; | 1236 name.unique_id = device_id; |
| 1263 | 1237 |
| 1264 return new WebContentsVideoCaptureDevice( | 1238 return new WebContentsVideoCaptureDevice( |
| 1265 name, render_process_id, render_view_id); | 1239 name, render_process_id, render_view_id, destroy_cb); |
| 1266 } | |
| 1267 | |
| 1268 // static | |
| 1269 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::CreateForTesting( | |
| 1270 RenderWidgetHost* test_source, const base::Closure& destroy_cb) { | |
| 1271 return new WebContentsVideoCaptureDevice(test_source, destroy_cb); | |
| 1272 } | 1240 } |
| 1273 | 1241 |
| 1274 void WebContentsVideoCaptureDevice::Allocate( | 1242 void WebContentsVideoCaptureDevice::Allocate( |
| 1275 int width, int height, int frame_rate, | 1243 int width, int height, int frame_rate, |
| 1276 VideoCaptureDevice::EventHandler* consumer) { | 1244 VideoCaptureDevice::EventHandler* consumer) { |
| 1277 DCHECK(capturer_); | 1245 DCHECK(capturer_); |
| 1278 capturer_->SetConsumer(consumer); | 1246 capturer_->SetConsumer(consumer); |
| 1279 capturer_->Allocate(width, height, frame_rate); | 1247 capturer_->Allocate(width, height, frame_rate); |
| 1280 } | 1248 } |
| 1281 | 1249 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1294 capturer_->SetConsumer(NULL); | 1262 capturer_->SetConsumer(NULL); |
| 1295 capturer_->DeAllocate(); | 1263 capturer_->DeAllocate(); |
| 1296 } | 1264 } |
| 1297 | 1265 |
| 1298 const media::VideoCaptureDevice::Name& | 1266 const media::VideoCaptureDevice::Name& |
| 1299 WebContentsVideoCaptureDevice::device_name() { | 1267 WebContentsVideoCaptureDevice::device_name() { |
| 1300 return device_name_; | 1268 return device_name_; |
| 1301 } | 1269 } |
| 1302 | 1270 |
| 1303 } // namespace content | 1271 } // namespace content |
| OLD | NEW |