| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 } | 135 } |
| 136 // Make each dimension a positive, even number; if not already. | 136 // Make each dimension a positive, even number; if not already. |
| 137 fitted_width = std::max(kMinFrameWidth, MakeEven(fitted_width)); | 137 fitted_width = std::max(kMinFrameWidth, MakeEven(fitted_width)); |
| 138 fitted_height = std::max(kMinFrameHeight, MakeEven(fitted_height)); | 138 fitted_height = std::max(kMinFrameHeight, MakeEven(fitted_height)); |
| 139 | 139 |
| 140 *fitted_size = gfx::Size(fitted_width, fitted_height); | 140 *fitted_size = gfx::Size(fitted_width, fitted_height); |
| 141 } | 141 } |
| 142 | 142 |
| 143 // Keeps track of the RenderView to be sourced, and executes copying of the | 143 // Keeps track of the RenderView to be sourced, and executes copying of the |
| 144 // backing store on the UI BrowserThread. | 144 // backing store on the UI BrowserThread. |
| 145 class BackingStoreCopier : public content::WebContentsObserver { | 145 class BackingStoreCopier : public WebContentsObserver { |
| 146 public: | 146 public: |
| 147 // Result status and done callback used with StartCopy(). | 147 // Result status and done callback used with StartCopy(). |
| 148 enum Result { | 148 enum Result { |
| 149 OK, | 149 OK, |
| 150 TRANSIENT_ERROR, | 150 TRANSIENT_ERROR, |
| 151 NO_SOURCE, | 151 NO_SOURCE, |
| 152 }; | 152 }; |
| 153 typedef base::Callback<void(Result result, | 153 typedef base::Callback<void(Result result, |
| 154 scoped_ptr<skia::PlatformBitmap> capture, | 154 scoped_ptr<skia::PlatformBitmap> capture, |
| 155 const base::Time& capture_time)> DoneCB; | 155 const base::Time& capture_time)> DoneCB; |
| 156 | 156 |
| 157 BackingStoreCopier(int render_process_id, int render_view_id); | 157 BackingStoreCopier(int render_process_id, int render_view_id); |
| 158 | 158 |
| 159 // If non-NULL, use the given |override| to access the backing store. | 159 // If non-NULL, use the given |override| to access the backing store. |
| 160 // This is used for unit testing. | 160 // This is used for unit testing. |
| 161 void SetRenderWidgetHostForTesting(content::RenderWidgetHost* override); | 161 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); |
| 162 | 162 |
| 163 // Starts the copy from the backing store. Must be run on the UI | 163 // Starts the copy from the backing store. Must be run on the UI |
| 164 // BrowserThread. |done_cb| is invoked with result status. When successful | 164 // BrowserThread. |done_cb| is invoked with result status. When successful |
| 165 // (OK), the bitmap of the capture is transferred to the callback along with | 165 // (OK), the bitmap of the capture is transferred to the callback along with |
| 166 // the timestamp at which the capture was completed. | 166 // the timestamp at which the capture was completed. |
| 167 void StartCopy(int desired_width, int desired_height, const DoneCB& done_cb); | 167 void StartCopy(int desired_width, int desired_height, const DoneCB& done_cb); |
| 168 | 168 |
| 169 private: | 169 private: |
| 170 void LookUpAndObserveWebContents(); | 170 void LookUpAndObserveWebContents(); |
| 171 | 171 |
| 172 void CopyFromBackingStoreComplete(scoped_ptr<skia::PlatformBitmap> capture, | 172 void CopyFromBackingStoreComplete(scoped_ptr<skia::PlatformBitmap> capture, |
| 173 const DoneCB& done_cb, bool success); | 173 const DoneCB& done_cb, bool success); |
| 174 | 174 |
| 175 // The "starting point" to find the capture source. | 175 // The "starting point" to find the capture source. |
| 176 const int render_process_id_; | 176 const int render_process_id_; |
| 177 const int render_view_id_; | 177 const int render_view_id_; |
| 178 | 178 |
| 179 // If the following is NULL (normal behavior), the implementation should | 179 // If the following is NULL (normal behavior), the implementation should |
| 180 // access RenderWidgetHost via web_contents(). | 180 // access RenderWidgetHost via web_contents(). |
| 181 content::RenderWidgetHost* rwh_for_testing_; | 181 RenderWidgetHost* rwh_for_testing_; |
| 182 | 182 |
| 183 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); | 183 DISALLOW_COPY_AND_ASSIGN(BackingStoreCopier); |
| 184 }; | 184 }; |
| 185 | 185 |
| 186 // Renders captures (from the backing store) into video frame buffers on a | 186 // Renders captures (from the backing store) into video frame buffers on a |
| 187 // separate thread. Manages use of internally-owned video frame buffers. | 187 // separate thread. Manages use of internally-owned video frame buffers. |
| 188 class VideoFrameRenderer { | 188 class VideoFrameRenderer { |
| 189 public: | 189 public: |
| 190 typedef base::Callback<void(const SkBitmap*)> DoneCB; | 190 typedef base::Callback<void(const SkBitmap*)> DoneCB; |
| 191 | 191 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 263 |
| 264 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); | 264 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); |
| 265 }; | 265 }; |
| 266 | 266 |
| 267 BackingStoreCopier::BackingStoreCopier(int render_process_id, | 267 BackingStoreCopier::BackingStoreCopier(int render_process_id, |
| 268 int render_view_id) | 268 int render_view_id) |
| 269 : render_process_id_(render_process_id), render_view_id_(render_view_id), | 269 : render_process_id_(render_process_id), render_view_id_(render_view_id), |
| 270 rwh_for_testing_(NULL) {} | 270 rwh_for_testing_(NULL) {} |
| 271 | 271 |
| 272 void BackingStoreCopier::LookUpAndObserveWebContents() { | 272 void BackingStoreCopier::LookUpAndObserveWebContents() { |
| 273 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 274 | 274 |
| 275 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. | 275 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. |
| 276 // If successful, begin observing the WebContents instance. If unsuccessful, | 276 // If successful, begin observing the WebContents instance. If unsuccessful, |
| 277 // stop observing and post an error. | 277 // stop observing and post an error. |
| 278 // | 278 // |
| 279 // Why this can be unsuccessful: The request for mirroring originates in a | 279 // Why this can be unsuccessful: The request for mirroring originates in a |
| 280 // render process, and this request is based on the current RenderView | 280 // render process, and this request is based on the current RenderView |
| 281 // associated with a tab. However, by the time we get up-and-running here, | 281 // associated with a tab. However, by the time we get up-and-running here, |
| 282 // there have been multiple back-and-forth IPCs between processes, as well as | 282 // there have been multiple back-and-forth IPCs between processes, as well as |
| 283 // a bit of indirection across threads. It's easily possible that, in the | 283 // a bit of indirection across threads. It's easily possible that, in the |
| 284 // meantime, the original RenderView may have gone away. | 284 // meantime, the original RenderView may have gone away. |
| 285 content::RenderViewHost* const rvh = | 285 RenderViewHost* const rvh = |
| 286 content::RenderViewHost::FromID(render_process_id_, render_view_id_); | 286 RenderViewHost::FromID(render_process_id_, render_view_id_); |
| 287 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" | 287 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" |
| 288 << render_process_id_ << ", " << render_view_id_ | 288 << render_process_id_ << ", " << render_view_id_ |
| 289 << ") returned NULL."; | 289 << ") returned NULL."; |
| 290 Observe(rvh ? content::WebContents::FromRenderViewHost(rvh) : NULL); | 290 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); |
| 291 DVLOG_IF(1, !web_contents()) | 291 DVLOG_IF(1, !web_contents()) |
| 292 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; | 292 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; |
| 293 } | 293 } |
| 294 | 294 |
| 295 void BackingStoreCopier::SetRenderWidgetHostForTesting( | 295 void BackingStoreCopier::SetRenderWidgetHostForTesting( |
| 296 content::RenderWidgetHost* override) { | 296 RenderWidgetHost* override) { |
| 297 rwh_for_testing_ = override; | 297 rwh_for_testing_ = override; |
| 298 } | 298 } |
| 299 | 299 |
| 300 void BackingStoreCopier::StartCopy(int desired_width, int desired_height, | 300 void BackingStoreCopier::StartCopy(int desired_width, int desired_height, |
| 301 const DoneCB& done_cb) { | 301 const DoneCB& done_cb) { |
| 302 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 303 | 303 |
| 304 TRACE_EVENT_ASYNC_BEGIN0("mirroring", "Capture", this); | 304 TRACE_EVENT_ASYNC_BEGIN0("mirroring", "Capture", this); |
| 305 | 305 |
| 306 content::RenderWidgetHost* rwh; | 306 RenderWidgetHost* rwh; |
| 307 if (rwh_for_testing_) { | 307 if (rwh_for_testing_) { |
| 308 rwh = rwh_for_testing_; | 308 rwh = rwh_for_testing_; |
| 309 } else { | 309 } else { |
| 310 if (!web_contents()) { // No source yet. | 310 if (!web_contents()) { // No source yet. |
| 311 LookUpAndObserveWebContents(); | 311 LookUpAndObserveWebContents(); |
| 312 if (!web_contents()) { // No source ever. | 312 if (!web_contents()) { // No source ever. |
| 313 done_cb.Run(NO_SOURCE, | 313 done_cb.Run(NO_SOURCE, |
| 314 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); | 314 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); |
| 315 return; | 315 return; |
| 316 } | 316 } |
| 317 } | 317 } |
| 318 rwh = web_contents()->GetRenderViewHost(); | 318 rwh = web_contents()->GetRenderViewHost(); |
| 319 if (!rwh) { | 319 if (!rwh) { |
| 320 // Transient failure state (e.g., a RenderView is being replaced). | 320 // Transient failure state (e.g., a RenderView is being replaced). |
| 321 done_cb.Run(TRANSIENT_ERROR, | 321 done_cb.Run(TRANSIENT_ERROR, |
| 322 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); | 322 scoped_ptr<skia::PlatformBitmap>(NULL), base::Time()); |
| 323 return; | 323 return; |
| 324 } | 324 } |
| 325 } | 325 } |
| 326 | 326 |
| 327 gfx::Size fitted_size; | 327 gfx::Size fitted_size; |
| 328 if (content::RenderWidgetHostView* const view = rwh->GetView()) { | 328 if (RenderWidgetHostView* const view = rwh->GetView()) { |
| 329 const gfx::Size& view_size = view->GetViewBounds().size(); | 329 const gfx::Size& view_size = view->GetViewBounds().size(); |
| 330 if (!view_size.IsEmpty()) { | 330 if (!view_size.IsEmpty()) { |
| 331 CalculateFittedSize(view_size.width(), view_size.height(), | 331 CalculateFittedSize(view_size.width(), view_size.height(), |
| 332 desired_width, desired_height, | 332 desired_width, desired_height, |
| 333 &fitted_size); | 333 &fitted_size); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 | 336 |
| 337 // TODO(miu): Look into tweaking the interface to CopyFromBackingStore, since | 337 // TODO(miu): Look into tweaking the interface to CopyFromBackingStore, since |
| 338 // it seems poor to have to allocate a new skia::PlatformBitmap as an output | 338 // it seems poor to have to allocate a new skia::PlatformBitmap as an output |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 // | 600 // |
| 601 // CaptureMachine manages a simple state machine and the pipeline (see notes at | 601 // CaptureMachine manages a simple state machine and the pipeline (see notes at |
| 602 // top of this file). It times the start of successive captures and | 602 // top of this file). It times the start of successive captures and |
| 603 // facilitates the processing of each through the stages of the pipeline. | 603 // facilitates the processing of each through the stages of the pipeline. |
| 604 class CaptureMachine | 604 class CaptureMachine |
| 605 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> { | 605 : public base::RefCountedThreadSafe<CaptureMachine, CaptureMachine> { |
| 606 public: | 606 public: |
| 607 CaptureMachine(int render_process_id, int render_view_id); | 607 CaptureMachine(int render_process_id, int render_view_id); |
| 608 | 608 |
| 609 // Set capture source to the given |override| for unit testing. | 609 // Set capture source to the given |override| for unit testing. |
| 610 void SetRenderWidgetHostForTesting(content::RenderWidgetHost* override); | 610 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); |
| 611 | 611 |
| 612 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove | 612 // Synchronously sets/unsets the consumer. Pass |consumer| as NULL to remove |
| 613 // the reference to the consumer; then, once this method returns, | 613 // the reference to the consumer; then, once this method returns, |
| 614 // CaptureMachine will no longer invoke callbacks on the old consumer from any | 614 // CaptureMachine will no longer invoke callbacks on the old consumer from any |
| 615 // thread. | 615 // thread. |
| 616 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer); | 616 void SetConsumer(media::VideoCaptureDevice::EventHandler* consumer); |
| 617 | 617 |
| 618 // Asynchronous requests to change CaptureMachine state. | 618 // Asynchronous requests to change CaptureMachine state. |
| 619 void Allocate(int width, int height, int frame_rate); | 619 void Allocate(int width, int height, int frame_rate); |
| 620 void Start(); | 620 void Start(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 : manager_thread_("WebContentsVideo_ManagerThread"), | 685 : manager_thread_("WebContentsVideo_ManagerThread"), |
| 686 state_(kIdle), | 686 state_(kIdle), |
| 687 is_snapshotting_(false), | 687 is_snapshotting_(false), |
| 688 num_renders_pending_(0), | 688 num_renders_pending_(0), |
| 689 copier_(render_process_id, render_view_id), | 689 copier_(render_process_id, render_view_id), |
| 690 deliverer_(&consumer_) { | 690 deliverer_(&consumer_) { |
| 691 manager_thread_.Start(); | 691 manager_thread_.Start(); |
| 692 } | 692 } |
| 693 | 693 |
| 694 void CaptureMachine::SetRenderWidgetHostForTesting( | 694 void CaptureMachine::SetRenderWidgetHostForTesting( |
| 695 content::RenderWidgetHost* override) { | 695 RenderWidgetHost* override) { |
| 696 copier_.SetRenderWidgetHostForTesting(override); | 696 copier_.SetRenderWidgetHostForTesting(override); |
| 697 } | 697 } |
| 698 | 698 |
| 699 void CaptureMachine::SetConsumer( | 699 void CaptureMachine::SetConsumer( |
| 700 media::VideoCaptureDevice::EventHandler* consumer) { | 700 media::VideoCaptureDevice::EventHandler* consumer) { |
| 701 consumer_.SetConsumer(consumer); | 701 consumer_.SetConsumer(consumer); |
| 702 } | 702 } |
| 703 | 703 |
| 704 void CaptureMachine::Allocate(int width, int height, int frame_rate) { | 704 void CaptureMachine::Allocate(int width, int height, int frame_rate) { |
| 705 ENSURE_INVOKED_ON_THREAD(manager_thread_, | 705 ENSURE_INVOKED_ON_THREAD(manager_thread_, |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 // point (because CaptureMachine's ref-count is zero). | 793 // point (because CaptureMachine's ref-count is zero). |
| 794 } | 794 } |
| 795 | 795 |
| 796 // static | 796 // static |
| 797 void CaptureMachine::Destruct(const CaptureMachine* x) { | 797 void CaptureMachine::Destruct(const CaptureMachine* x) { |
| 798 // The current thread is very likely to be one owned by CaptureMachine. When | 798 // The current thread is very likely to be one owned by CaptureMachine. When |
| 799 // ~CaptureMachine() is called, it will attempt to join with the | 799 // ~CaptureMachine() is called, it will attempt to join with the |
| 800 // CaptureMachine-owned threads, including itself. Since it's illegal for a | 800 // CaptureMachine-owned threads, including itself. Since it's illegal for a |
| 801 // thread to join with itself, we need to trampoline the destructor call to | 801 // thread to join with itself, we need to trampoline the destructor call to |
| 802 // another thread. | 802 // another thread. |
| 803 content::BrowserThread::PostBlockingPoolTask( | 803 BrowserThread::PostBlockingPoolTask( |
| 804 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x)); | 804 FROM_HERE, base::Bind(&DeleteFromOutsideThread, x)); |
| 805 } | 805 } |
| 806 | 806 |
| 807 // static | 807 // static |
| 808 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) { | 808 void CaptureMachine::DeleteFromOutsideThread(const CaptureMachine* x) { |
| 809 // Note: Thread joins are about to happen here (in ~CaptureThread()). | 809 // Note: Thread joins are about to happen here (in ~CaptureThread()). |
| 810 delete x; | 810 delete x; |
| 811 } | 811 } |
| 812 | 812 |
| 813 void CaptureMachine::TransitionStateTo(State next_state) { | 813 void CaptureMachine::TransitionStateTo(State next_state) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 if (!is_snapshotting_) { | 866 if (!is_snapshotting_) { |
| 867 is_snapshotting_ = true; | 867 is_snapshotting_ = true; |
| 868 | 868 |
| 869 const BackingStoreCopier::DoneCB& done_cb = | 869 const BackingStoreCopier::DoneCB& done_cb = |
| 870 media::BindToLoop(manager_thread_.message_loop_proxy(), | 870 media::BindToLoop(manager_thread_.message_loop_proxy(), |
| 871 base::Bind(&CaptureMachine::SnapshotComplete, this)); | 871 base::Bind(&CaptureMachine::SnapshotComplete, this)); |
| 872 const base::Closure& start_cb = | 872 const base::Closure& start_cb = |
| 873 base::Bind(&BackingStoreCopier::StartCopy, | 873 base::Bind(&BackingStoreCopier::StartCopy, |
| 874 base::Unretained(&copier_), | 874 base::Unretained(&copier_), |
| 875 settings_.width, settings_.height, done_cb); | 875 settings_.width, settings_.height, done_cb); |
| 876 content::BrowserThread::PostTask( | 876 BrowserThread::PostTask( |
| 877 content::BrowserThread::UI, FROM_HERE, start_cb); | 877 BrowserThread::UI, FROM_HERE, start_cb); |
| 878 } | 878 } |
| 879 | 879 |
| 880 ScheduleNextFrameCapture(); | 880 ScheduleNextFrameCapture(); |
| 881 } | 881 } |
| 882 | 882 |
| 883 void CaptureMachine::SnapshotComplete(BackingStoreCopier::Result result, | 883 void CaptureMachine::SnapshotComplete(BackingStoreCopier::Result result, |
| 884 scoped_ptr<skia::PlatformBitmap> capture, | 884 scoped_ptr<skia::PlatformBitmap> capture, |
| 885 const base::Time& capture_time) { | 885 const base::Time& capture_time) { |
| 886 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current()); | 886 DCHECK_EQ(manager_thread_.message_loop(), MessageLoop::current()); |
| 887 | 887 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 renderer_.Release(frame_buffer); | 940 renderer_.Release(frame_buffer); |
| 941 } | 941 } |
| 942 | 942 |
| 943 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( | 943 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( |
| 944 const media::VideoCaptureDevice::Name& name, | 944 const media::VideoCaptureDevice::Name& name, |
| 945 int render_process_id, int render_view_id) | 945 int render_process_id, int render_view_id) |
| 946 : device_name_(name), | 946 : device_name_(name), |
| 947 capturer_(new CaptureMachine(render_process_id, render_view_id)) {} | 947 capturer_(new CaptureMachine(render_process_id, render_view_id)) {} |
| 948 | 948 |
| 949 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( | 949 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( |
| 950 content::RenderWidgetHost* test_source) | 950 RenderWidgetHost* test_source) |
| 951 : capturer_(new CaptureMachine(-1, -1)) { | 951 : capturer_(new CaptureMachine(-1, -1)) { |
| 952 device_name_.device_name = "WebContentsForTesting"; | 952 device_name_.device_name = "WebContentsForTesting"; |
| 953 device_name_.unique_id = "-1:-1"; | 953 device_name_.unique_id = "-1:-1"; |
| 954 capturer_->SetRenderWidgetHostForTesting(test_source); | 954 capturer_->SetRenderWidgetHostForTesting(test_source); |
| 955 } | 955 } |
| 956 | 956 |
| 957 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { | 957 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { |
| 958 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; | 958 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; |
| 959 } | 959 } |
| 960 | 960 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 981 "WebContents[%.*s]", | 981 "WebContents[%.*s]", |
| 982 static_cast<int>(device_id.size()), device_id.data()); | 982 static_cast<int>(device_id.size()), device_id.data()); |
| 983 name.unique_id = device_id; | 983 name.unique_id = device_id; |
| 984 | 984 |
| 985 return new WebContentsVideoCaptureDevice( | 985 return new WebContentsVideoCaptureDevice( |
| 986 name, render_process_id, render_view_id); | 986 name, render_process_id, render_view_id); |
| 987 } | 987 } |
| 988 | 988 |
| 989 // static | 989 // static |
| 990 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::CreateForTesting( | 990 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::CreateForTesting( |
| 991 content::RenderWidgetHost* test_source) { | 991 RenderWidgetHost* test_source) { |
| 992 return new WebContentsVideoCaptureDevice(test_source); | 992 return new WebContentsVideoCaptureDevice(test_source); |
| 993 } | 993 } |
| 994 | 994 |
| 995 void WebContentsVideoCaptureDevice::Allocate( | 995 void WebContentsVideoCaptureDevice::Allocate( |
| 996 int width, int height, int frame_rate, | 996 int width, int height, int frame_rate, |
| 997 VideoCaptureDevice::EventHandler* consumer) { | 997 VideoCaptureDevice::EventHandler* consumer) { |
| 998 DCHECK(capturer_); | 998 DCHECK(capturer_); |
| 999 capturer_->SetConsumer(consumer); | 999 capturer_->SetConsumer(consumer); |
| 1000 capturer_->Allocate(width, height, frame_rate); | 1000 capturer_->Allocate(width, height, frame_rate); |
| 1001 } | 1001 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1015 capturer_->SetConsumer(NULL); | 1015 capturer_->SetConsumer(NULL); |
| 1016 capturer_->DeAllocate(); | 1016 capturer_->DeAllocate(); |
| 1017 } | 1017 } |
| 1018 | 1018 |
| 1019 const media::VideoCaptureDevice::Name& | 1019 const media::VideoCaptureDevice::Name& |
| 1020 WebContentsVideoCaptureDevice::device_name() { | 1020 WebContentsVideoCaptureDevice::device_name() { |
| 1021 return device_name_; | 1021 return device_name_; |
| 1022 } | 1022 } |
| 1023 | 1023 |
| 1024 } // namespace content | 1024 } // namespace content |
| OLD | NEW |