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 about interactions with VideoCaptureImpl. | 5 // Implementation notes about interactions with VideoCaptureImpl. |
6 // | 6 // |
7 // How is VideoCaptureImpl used: | 7 // How is VideoCaptureImpl used: |
8 // | 8 // |
9 // VideoCaptureImpl is an IO thread object while VideoCaptureImplManager | 9 // VideoCaptureImpl is an IO thread object while VideoCaptureImplManager |
10 // lives only on the render thread. It is only possible to access an | 10 // lives only on the render thread. It is only possible to access an |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "content/child/child_process.h" | 29 #include "content/child/child_process.h" |
30 #include "content/renderer/media/video_capture_impl.h" | 30 #include "content/renderer/media/video_capture_impl.h" |
31 #include "content/renderer/media/video_capture_message_filter.h" | 31 #include "content/renderer/media/video_capture_message_filter.h" |
32 #include "media/base/bind_to_current_loop.h" | 32 #include "media/base/bind_to_current_loop.h" |
33 | 33 |
34 namespace content { | 34 namespace content { |
35 | 35 |
36 VideoCaptureImplManager::VideoCaptureImplManager() | 36 VideoCaptureImplManager::VideoCaptureImplManager() |
37 : next_client_id_(0), | 37 : next_client_id_(0), |
38 filter_(new VideoCaptureMessageFilter()), | 38 filter_(new VideoCaptureMessageFilter()), |
| 39 render_main_message_loop_(base::MessageLoopProxy::current()), |
39 weak_factory_(this) { | 40 weak_factory_(this) { |
40 } | 41 } |
41 | 42 |
42 VideoCaptureImplManager::~VideoCaptureImplManager() { | 43 VideoCaptureImplManager::~VideoCaptureImplManager() { |
43 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 44 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
44 if (devices_.empty()) | 45 if (devices_.empty()) |
45 return; | 46 return; |
46 // Forcibly release all video capture resources. | 47 // Forcibly release all video capture resources. |
47 for (const auto& device : devices_) { | 48 for (const auto& device : devices_) { |
48 VideoCaptureImpl* const impl = device.second.second; | 49 VideoCaptureImpl* const impl = device.second.second; |
49 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 50 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
50 FROM_HERE, | 51 FROM_HERE, |
51 base::Bind(&VideoCaptureImpl::DeInit, | 52 base::Bind(&VideoCaptureImpl::DeInit, |
52 base::Unretained(impl))); | 53 base::Unretained(impl))); |
53 ChildProcess::current()->io_message_loop_proxy()->DeleteSoon(FROM_HERE, | 54 ChildProcess::current()->io_message_loop_proxy()->DeleteSoon(FROM_HERE, |
54 impl); | 55 impl); |
55 } | 56 } |
56 devices_.clear(); | 57 devices_.clear(); |
57 } | 58 } |
58 | 59 |
59 base::Closure VideoCaptureImplManager::UseDevice( | 60 base::Closure VideoCaptureImplManager::UseDevice( |
60 media::VideoCaptureSessionId id) { | 61 media::VideoCaptureSessionId id) { |
61 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 62 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
62 | 63 |
63 VideoCaptureImpl* impl = NULL; | 64 VideoCaptureImpl* impl = NULL; |
64 const VideoCaptureDeviceMap::iterator it = devices_.find(id); | 65 const VideoCaptureDeviceMap::iterator it = devices_.find(id); |
65 if (it == devices_.end()) { | 66 if (it == devices_.end()) { |
66 impl = CreateVideoCaptureImplForTesting(id, filter_.get()); | 67 impl = CreateVideoCaptureImplForTesting(id, filter_.get()); |
67 if (!impl) | 68 if (!impl) |
68 impl = new VideoCaptureImpl(id, filter_.get()); | 69 impl = new VideoCaptureImpl(id, filter_.get()); |
69 devices_[id] = std::make_pair(1, impl); | 70 devices_[id] = std::make_pair(1, impl); |
70 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 71 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
71 FROM_HERE, | 72 FROM_HERE, |
72 base::Bind(&VideoCaptureImpl::Init, | 73 base::Bind(&VideoCaptureImpl::Init, |
73 base::Unretained(impl))); | 74 base::Unretained(impl))); |
74 } else { | 75 } else { |
75 ++it->second.first; | 76 ++it->second.first; |
76 } | 77 } |
77 return base::Bind(&VideoCaptureImplManager::UnrefDevice, | 78 return base::Bind(&VideoCaptureImplManager::UnrefDevice, |
78 weak_factory_.GetWeakPtr(), id); | 79 weak_factory_.GetWeakPtr(), id); |
79 } | 80 } |
80 | 81 |
81 base::Closure VideoCaptureImplManager::StartCapture( | 82 base::Closure VideoCaptureImplManager::StartCapture( |
82 media::VideoCaptureSessionId id, | 83 media::VideoCaptureSessionId id, |
83 const media::VideoCaptureParams& params, | 84 const media::VideoCaptureParams& params, |
84 const VideoCaptureStateUpdateCB& state_update_cb, | 85 const VideoCaptureStateUpdateCB& state_update_cb, |
85 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { | 86 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { |
86 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 87 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
87 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); | 88 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); |
88 DCHECK(it != devices_.end()); | 89 DCHECK(it != devices_.end()); |
89 VideoCaptureImpl* const impl = it->second.second; | 90 VideoCaptureImpl* const impl = it->second.second; |
90 | 91 |
91 // This ID is used to identify a client of VideoCaptureImpl. | 92 // This ID is used to identify a client of VideoCaptureImpl. |
92 const int client_id = ++next_client_id_; | 93 const int client_id = ++next_client_id_; |
93 | 94 |
94 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 95 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
95 FROM_HERE, | 96 FROM_HERE, |
96 base::Bind(&VideoCaptureImpl::StartCapture, | 97 base::Bind(&VideoCaptureImpl::StartCapture, |
97 base::Unretained(impl), | 98 base::Unretained(impl), |
98 client_id, | 99 client_id, |
99 params, | 100 params, |
100 state_update_cb, | 101 state_update_cb, |
101 deliver_frame_cb)); | 102 deliver_frame_cb)); |
102 return base::Bind(&VideoCaptureImplManager::StopCapture, | 103 return base::Bind(&VideoCaptureImplManager::StopCapture, |
103 weak_factory_.GetWeakPtr(), | 104 weak_factory_.GetWeakPtr(), |
104 client_id, id); | 105 client_id, id); |
105 } | 106 } |
106 | 107 |
107 void VideoCaptureImplManager::GetDeviceSupportedFormats( | 108 void VideoCaptureImplManager::GetDeviceSupportedFormats( |
108 media::VideoCaptureSessionId id, | 109 media::VideoCaptureSessionId id, |
109 const VideoCaptureDeviceFormatsCB& callback) { | 110 const VideoCaptureDeviceFormatsCB& callback) { |
110 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 111 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
111 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); | 112 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); |
112 DCHECK(it != devices_.end()); | 113 DCHECK(it != devices_.end()); |
113 VideoCaptureImpl* const impl = it->second.second; | 114 VideoCaptureImpl* const impl = it->second.second; |
114 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 115 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
115 FROM_HERE, | 116 FROM_HERE, |
116 base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats, | 117 base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats, |
117 base::Unretained(impl), callback)); | 118 base::Unretained(impl), callback)); |
118 } | 119 } |
119 | 120 |
120 void VideoCaptureImplManager::GetDeviceFormatsInUse( | 121 void VideoCaptureImplManager::GetDeviceFormatsInUse( |
121 media::VideoCaptureSessionId id, | 122 media::VideoCaptureSessionId id, |
122 const VideoCaptureDeviceFormatsCB& callback) { | 123 const VideoCaptureDeviceFormatsCB& callback) { |
123 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 124 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
124 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); | 125 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); |
125 DCHECK(it != devices_.end()); | 126 DCHECK(it != devices_.end()); |
126 VideoCaptureImpl* const impl = it->second.second; | 127 VideoCaptureImpl* const impl = it->second.second; |
127 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 128 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
128 FROM_HERE, | 129 FROM_HERE, |
129 base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse, | 130 base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse, |
130 base::Unretained(impl), callback)); | 131 base::Unretained(impl), callback)); |
131 } | 132 } |
132 | 133 |
133 VideoCaptureImpl* | 134 VideoCaptureImpl* |
134 VideoCaptureImplManager::CreateVideoCaptureImplForTesting( | 135 VideoCaptureImplManager::CreateVideoCaptureImplForTesting( |
135 media::VideoCaptureSessionId id, | 136 media::VideoCaptureSessionId id, |
136 VideoCaptureMessageFilter* filter) const { | 137 VideoCaptureMessageFilter* filter) const { |
137 return NULL; | 138 return NULL; |
138 } | 139 } |
139 | 140 |
140 void VideoCaptureImplManager::StopCapture( | 141 void VideoCaptureImplManager::StopCapture(int client_id, |
141 int client_id, media::VideoCaptureSessionId id) { | 142 media::VideoCaptureSessionId id) { |
142 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 143 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
143 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); | 144 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id); |
144 DCHECK(it != devices_.end()); | 145 DCHECK(it != devices_.end()); |
145 VideoCaptureImpl* const impl = it->second.second; | 146 VideoCaptureImpl* const impl = it->second.second; |
146 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 147 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
147 FROM_HERE, | 148 FROM_HERE, |
148 base::Bind(&VideoCaptureImpl::StopCapture, | 149 base::Bind(&VideoCaptureImpl::StopCapture, |
149 base::Unretained(impl), client_id)); | 150 base::Unretained(impl), client_id)); |
150 } | 151 } |
151 | 152 |
152 void VideoCaptureImplManager::UnrefDevice( | 153 void VideoCaptureImplManager::UnrefDevice( |
153 media::VideoCaptureSessionId id) { | 154 media::VideoCaptureSessionId id) { |
154 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 155 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
155 const VideoCaptureDeviceMap::iterator it = devices_.find(id); | 156 const VideoCaptureDeviceMap::iterator it = devices_.find(id); |
156 DCHECK(it != devices_.end()); | 157 DCHECK(it != devices_.end()); |
157 VideoCaptureImpl* const impl = it->second.second; | 158 VideoCaptureImpl* const impl = it->second.second; |
158 | 159 |
159 // Unref and destroy on the IO thread if there's no more client. | 160 // Unref and destroy on the IO thread if there's no more client. |
160 DCHECK(it->second.first); | 161 DCHECK(it->second.first); |
161 --it->second.first; | 162 --it->second.first; |
162 if (!it->second.first) { | 163 if (!it->second.first) { |
163 devices_.erase(id); | 164 devices_.erase(id); |
164 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 165 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
165 FROM_HERE, | 166 FROM_HERE, |
166 base::Bind(&VideoCaptureImpl::DeInit, | 167 base::Bind(&VideoCaptureImpl::DeInit, |
167 base::Unretained(impl))); | 168 base::Unretained(impl))); |
168 ChildProcess::current()->io_message_loop_proxy()->DeleteSoon(FROM_HERE, | 169 ChildProcess::current()->io_message_loop_proxy()->DeleteSoon(FROM_HERE, |
169 impl); | 170 impl); |
170 } | 171 } |
171 } | 172 } |
172 | 173 |
173 void VideoCaptureImplManager::SuspendDevices(bool suspend) { | 174 void VideoCaptureImplManager::SuspendDevices(bool suspend) { |
174 DCHECK(render_main_thread_checker_.CalledOnValidThread()); | 175 DCHECK(render_main_message_loop_->BelongsToCurrentThread()); |
175 for (const auto& device : devices_) { | 176 for (const auto& device : devices_) { |
176 VideoCaptureImpl* const impl = device.second.second; | 177 VideoCaptureImpl* const impl = device.second.second; |
177 ChildProcess::current()->io_message_loop_proxy()->PostTask( | 178 ChildProcess::current()->io_message_loop_proxy()->PostTask( |
178 FROM_HERE, | 179 FROM_HERE, base::Bind(&VideoCaptureImpl::SuspendCapture, |
179 base::Bind(&VideoCaptureImpl::SuspendCapture, | 180 base::Unretained(impl), suspend)); |
180 base::Unretained(impl), suspend)); | |
181 } | 181 } |
182 } | 182 } |
183 | 183 |
184 } // namespace content | 184 } // namespace content |
OLD | NEW |