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 #include "content/renderer/media/video_capture_impl_manager.h" | 5 #include "content/renderer/media/video_capture_impl_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/stl_util.h" |
9 #include "content/public/renderer/render_thread.h" | |
10 #include "content/renderer/media/video_capture_impl.h" | 9 #include "content/renderer/media/video_capture_impl.h" |
11 #include "content/renderer/media/video_capture_message_filter.h" | 10 #include "content/renderer/media/video_capture_message_filter.h" |
12 #include "media/base/bind_to_current_loop.h" | |
13 | 11 |
14 namespace content { | 12 namespace content { |
15 | 13 |
16 VideoCaptureHandle::VideoCaptureHandle( | 14 VideoCaptureImplManager::VideoCaptureImplManager() |
17 media::VideoCapture* impl, base::Closure destruction_cb) | 15 : thread_("VC manager") { |
18 : impl_(impl), destruction_cb_(destruction_cb) { | 16 thread_.Start(); |
| 17 message_loop_proxy_ = thread_.message_loop_proxy(); |
| 18 filter_ = new VideoCaptureMessageFilter(); |
19 } | 19 } |
20 | 20 |
21 VideoCaptureHandle::~VideoCaptureHandle() { | 21 media::VideoCapture* VideoCaptureImplManager::AddDevice( |
22 destruction_cb_.Run(); | 22 media::VideoCaptureSessionId id, |
| 23 media::VideoCapture::EventHandler* handler) { |
| 24 DCHECK(handler); |
| 25 |
| 26 base::AutoLock auto_lock(lock_); |
| 27 Devices::iterator it = devices_.find(id); |
| 28 if (it == devices_.end()) { |
| 29 VideoCaptureImpl* vc = |
| 30 new VideoCaptureImpl(id, message_loop_proxy_.get(), filter_.get()); |
| 31 devices_[id] = new Device(vc, handler); |
| 32 vc->Init(); |
| 33 return vc; |
| 34 } |
| 35 |
| 36 devices_[id]->clients.push_front(handler); |
| 37 return it->second->vc; |
23 } | 38 } |
24 | 39 |
25 void VideoCaptureHandle::StartCapture( | 40 void VideoCaptureImplManager::SuspendDevices(bool suspend) { |
26 EventHandler* handler, | 41 base::AutoLock auto_lock(lock_); |
27 const media::VideoCaptureParams& params) { | 42 for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) |
28 impl_->StartCapture(handler, params); | 43 it->second->vc->SuspendCapture(suspend); |
29 } | 44 } |
30 | 45 |
31 void VideoCaptureHandle::StopCapture(EventHandler* handler) { | 46 void VideoCaptureImplManager::RemoveDevice( |
32 impl_->StopCapture(handler); | 47 media::VideoCaptureSessionId id, |
| 48 media::VideoCapture::EventHandler* handler) { |
| 49 DCHECK(handler); |
| 50 |
| 51 base::AutoLock auto_lock(lock_); |
| 52 Devices::iterator it = devices_.find(id); |
| 53 if (it == devices_.end()) |
| 54 return; |
| 55 |
| 56 size_t size = it->second->clients.size(); |
| 57 it->second->clients.remove(handler); |
| 58 |
| 59 if (size == it->second->clients.size() || size > 1) |
| 60 return; |
| 61 |
| 62 devices_[id]->vc->DeInit(base::Bind(&VideoCaptureImplManager::FreeDevice, |
| 63 this, devices_[id]->vc)); |
| 64 delete devices_[id]; |
| 65 devices_.erase(id); |
33 } | 66 } |
34 | 67 |
35 bool VideoCaptureHandle::CaptureStarted() { | 68 void VideoCaptureImplManager::FreeDevice(VideoCaptureImpl* vc) { |
36 return impl_->CaptureStarted(); | 69 delete vc; |
37 } | |
38 | |
39 int VideoCaptureHandle::CaptureFrameRate() { | |
40 return impl_->CaptureFrameRate(); | |
41 } | |
42 | |
43 VideoCaptureImplManager::VideoCaptureImplManager() | |
44 : filter_(new VideoCaptureMessageFilter()), | |
45 weak_factory_(this) { | |
46 } | 70 } |
47 | 71 |
48 VideoCaptureImplManager::~VideoCaptureImplManager() { | 72 VideoCaptureImplManager::~VideoCaptureImplManager() { |
49 DCHECK(thread_checker_.CalledOnValidThread()); | 73 thread_.Stop(); |
| 74 // TODO(wjia): uncomment the line below after collecting enough info for |
| 75 // crbug.com/152418. |
| 76 // STLDeleteContainerPairSecondPointers(devices_.begin(), devices_.end()); |
50 } | 77 } |
51 | 78 |
52 scoped_ptr<VideoCaptureHandle> VideoCaptureImplManager::UseDevice( | 79 VideoCaptureImplManager::Device::Device( |
53 media::VideoCaptureSessionId id) { | 80 VideoCaptureImpl* device, |
54 DCHECK(thread_checker_.CalledOnValidThread()); | 81 media::VideoCapture::EventHandler* handler) |
55 | 82 : vc(device) { |
56 VideoCaptureImpl* video_capture_device = NULL; | 83 clients.push_front(handler); |
57 VideoCaptureDeviceMap::iterator it = devices_.find(id); | |
58 if (it == devices_.end()) { | |
59 video_capture_device = CreateVideoCaptureImpl(id, filter_.get()); | |
60 devices_[id] = | |
61 std::make_pair(1, linked_ptr<VideoCaptureImpl>(video_capture_device)); | |
62 video_capture_device->Init(); | |
63 } else { | |
64 ++it->second.first; | |
65 video_capture_device = it->second.second.get(); | |
66 } | |
67 | |
68 // This callback ensures UnrefDevice() happens on the render thread. | |
69 return scoped_ptr<VideoCaptureHandle>( | |
70 new VideoCaptureHandle( | |
71 video_capture_device, | |
72 media::BindToCurrentLoop( | |
73 base::Bind( | |
74 &VideoCaptureImplManager::UnrefDevice, | |
75 weak_factory_.GetWeakPtr(), | |
76 id)))); | |
77 } | 84 } |
78 | 85 |
79 VideoCaptureImpl* VideoCaptureImplManager::CreateVideoCaptureImpl( | 86 VideoCaptureImplManager::Device::~Device() {} |
80 media::VideoCaptureSessionId id, | |
81 VideoCaptureMessageFilter* filter) const { | |
82 return new VideoCaptureImpl(id, filter); | |
83 } | |
84 | |
85 void VideoCaptureImplManager::UnrefDevice( | |
86 media::VideoCaptureSessionId id) { | |
87 DCHECK(thread_checker_.CalledOnValidThread()); | |
88 VideoCaptureDeviceMap::iterator it = devices_.find(id); | |
89 DCHECK(it != devices_.end()); | |
90 | |
91 DCHECK(it->second.first); | |
92 --it->second.first; | |
93 if (!it->second.first) { | |
94 VideoCaptureImpl* impl = it->second.second.release(); | |
95 devices_.erase(id); | |
96 impl->DeInit(base::Bind(&base::DeletePointer<VideoCaptureImpl>, impl)); | |
97 } | |
98 } | |
99 | |
100 void VideoCaptureImplManager::SuspendDevices(bool suspend) { | |
101 DCHECK(thread_checker_.CalledOnValidThread()); | |
102 for (VideoCaptureDeviceMap::iterator it = devices_.begin(); | |
103 it != devices_.end(); ++it) | |
104 it->second.second->SuspendCapture(suspend); | |
105 } | |
106 | 87 |
107 } // namespace content | 88 } // namespace content |
OLD | NEW |