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