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 |