OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/media_stream/video_capture_manager.h" | |
6 | |
7 #include "base/memory/scoped_ptr.h" | |
8 #include "content/browser/browser_thread.h" | |
9 #include "media/video/capture/fake_video_capture_device.h" | |
10 #include "media/video/capture/video_capture_device.h" | |
11 | |
12 namespace media_stream { | |
13 | |
14 // Starting id for the first capture session | |
brettw
2011/05/24 20:49:30
All of your comments should be complete sentences
wjia(left Chromium)
2011/05/31 18:47:03
Done.
| |
15 enum { kFirstSessionId = 2}; | |
brettw
2011/05/24 20:49:30
This value is a bit mysterious. The comment should
wjia(left Chromium)
2011/05/31 18:47:03
change it to kFirstSessionId = VideoCaptureManager
| |
16 | |
17 static ::base::LazyInstance<VideoCaptureManager> g_video_capture_manager( | |
18 base::LINKER_INITIALIZED); | |
19 | |
20 VideoCaptureManager* VideoCaptureManager::Get() { | |
21 return g_video_capture_manager.Pointer(); | |
22 } | |
23 | |
24 VideoCaptureManager::VideoCaptureManager() | |
25 : vc_device_thread_("VideoCaptureManagerThread"), | |
26 listener_(NULL), | |
27 new_capture_session_id_(kFirstSessionId), | |
28 devices_(), | |
29 use_fake_device_(false) { | |
30 vc_device_thread_.Start(); | |
31 } | |
32 | |
33 VideoCaptureManager::~VideoCaptureManager() { | |
34 vc_device_thread_.Stop(); | |
35 } | |
36 | |
37 bool VideoCaptureManager::Register(MediaStreamProviderListener* listener) { | |
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
39 DCHECK(!listener_); | |
40 listener_ = listener; | |
41 return true; | |
42 } | |
43 | |
44 void VideoCaptureManager::Unregister() { | |
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
46 listener_ = NULL; | |
47 } | |
48 | |
49 void VideoCaptureManager::EnumerateDevices() { | |
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
51 DCHECK(listener_); | |
52 | |
53 vc_device_thread_.message_loop()->PostTask( | |
54 FROM_HERE, | |
55 NewRunnableMethod(this, | |
56 &VideoCaptureManager::OnEnumerateDevices)); | |
57 } | |
58 | |
59 MediaCaptureSessionId VideoCaptureManager::Open( | |
60 const MediaCaptureDeviceInfo& device) { | |
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
62 DCHECK(listener_); | |
63 | |
64 // Generate a new id for this device | |
65 MediaCaptureSessionId video_capture_session_id = new_capture_session_id_++; | |
66 | |
67 vc_device_thread_.message_loop()->PostTask( | |
68 FROM_HERE, | |
69 NewRunnableMethod(this, | |
70 &VideoCaptureManager::OnOpen, | |
71 video_capture_session_id, | |
72 device)); | |
73 | |
74 return video_capture_session_id; | |
75 } | |
76 | |
77 void VideoCaptureManager::Close(MediaCaptureSessionId capture_session_id) { | |
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
79 DCHECK(listener_); | |
80 | |
81 vc_device_thread_.message_loop()->PostTask( | |
82 FROM_HERE, | |
83 NewRunnableMethod(this, | |
84 &VideoCaptureManager::OnClose, | |
85 capture_session_id)); | |
86 } | |
87 | |
88 void VideoCaptureManager::Start( | |
89 const media::VideoCaptureParams& capture_params, | |
90 media::VideoCaptureDevice::EventHandler* video_capture_receiver) { | |
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
92 | |
93 vc_device_thread_.message_loop()->PostTask( | |
94 FROM_HERE, | |
95 NewRunnableMethod(this, | |
96 &VideoCaptureManager::OnStart, | |
97 capture_params, | |
98 video_capture_receiver)); | |
99 } | |
100 | |
101 void VideoCaptureManager::Stop( | |
102 const media::VideoCaptureSessionId capture_session_id, Task* stopped_task) { | |
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
104 | |
105 vc_device_thread_.message_loop()->PostTask( | |
106 FROM_HERE, | |
107 NewRunnableMethod(this, | |
108 &VideoCaptureManager::OnStop, | |
109 capture_session_id, | |
110 stopped_task)); | |
111 } | |
112 | |
113 void VideoCaptureManager::UseFakeDevice() { | |
114 use_fake_device_ = true; | |
115 } | |
116 | |
117 MessageLoop* VideoCaptureManager::GetMessageLoop() { | |
118 return vc_device_thread_.message_loop(); | |
119 } | |
120 | |
121 void VideoCaptureManager::OnEnumerateDevices() { | |
122 DCHECK(IsOnCaptureDeviceThread()); | |
123 | |
124 scoped_ptr<media::VideoCaptureDevice::Names> device_names( | |
125 new media::VideoCaptureDevice::Names()); | |
126 GetAvailableDevices(device_names.get()); | |
127 | |
128 MediaCaptureDevices devices; | |
129 for (media::VideoCaptureDevice::Names::iterator it = | |
130 device_names.get()->begin(); it != device_names.get()->end(); ++it) { | |
brettw
2011/05/24 20:49:30
Wrapped lines should be indented to inside the (.
wjia(left Chromium)
2011/05/31 18:47:03
Done.
| |
131 bool opened = DeviceOpened(*it); | |
132 devices.push_back(MediaCaptureDeviceInfo(kVideoCapture, it->device_name, | |
133 it->unique_id, opened)); | |
134 } | |
135 | |
136 // Let the listener know the result | |
brettw
2011/05/24 20:49:30
This comment and the next one don't add any value,
wjia(left Chromium)
2011/05/31 18:47:03
Done.
| |
137 PostOnDevicesEnumerated(devices); | |
138 | |
139 // Clean-up | |
140 devices.clear(); | |
141 device_names.get()->clear(); | |
142 } | |
143 | |
144 void VideoCaptureManager::OnOpen(MediaCaptureSessionId capture_session_id, | |
145 const MediaCaptureDeviceInfo device) { | |
146 DCHECK(IsOnCaptureDeviceThread()); | |
147 DCHECK(devices_.find(capture_session_id) == devices_.end()); | |
148 | |
149 // Check if another session has already opened this device, only one user per | |
150 // device is supported. | |
151 if (DeviceOpened(device)) { | |
152 PostOnError(capture_session_id, kDeviceAlreadyInUse); | |
153 return; | |
154 } | |
155 | |
156 // Open the device | |
157 media::VideoCaptureDevice::Name vc_device_name; | |
158 vc_device_name.device_name = device.name; | |
159 vc_device_name.unique_id = device.device_id; | |
160 | |
161 media::VideoCaptureDevice* video_capture_device = NULL; | |
162 if (!use_fake_device_) { | |
163 video_capture_device = media::VideoCaptureDevice::Create(vc_device_name); | |
164 } else { | |
165 video_capture_device = | |
166 media::FakeVideoCaptureDevice::Create(vc_device_name); | |
167 } | |
168 if (video_capture_device == NULL) { | |
169 PostOnError(capture_session_id, kDeviceNotAvailable); | |
170 return; | |
171 } | |
172 | |
173 devices_[capture_session_id] = video_capture_device; | |
174 PostOnOpened(capture_session_id); | |
175 } | |
176 | |
177 void VideoCaptureManager::OnClose( | |
178 MediaCaptureSessionId capture_session_id) { | |
179 DCHECK(IsOnCaptureDeviceThread()); | |
180 | |
181 VideoCaptureDevices::iterator it = devices_.find(capture_session_id); | |
182 if (it != devices_.end()) { | |
183 // Deallocate (if not done already) and delete the device | |
184 media::VideoCaptureDevice* video_capture_device = it->second; | |
185 video_capture_device->DeAllocate(); | |
186 delete video_capture_device; | |
187 devices_.erase(it); | |
188 } | |
189 | |
190 PostOnClosed(capture_session_id); | |
191 } | |
192 | |
193 void VideoCaptureManager::OnStart( | |
194 const media::VideoCaptureParams capture_params, | |
195 media::VideoCaptureDevice::EventHandler* video_capture_receiver) { | |
196 DCHECK(IsOnCaptureDeviceThread()); | |
197 | |
198 // Solution for not using MediaStreamManager | |
199 // This session id won't be returned by Open() | |
200 if (capture_params.session_id == kStartOpenSessionId) { | |
201 // Start() is called without using Open(), we need to open a device | |
202 scoped_ptr<media::VideoCaptureDevice::Names> device_names( | |
203 new media::VideoCaptureDevice::Names()); | |
204 GetAvailableDevices(device_names.get()); | |
205 | |
206 MediaCaptureDeviceInfo device(kVideoCapture, | |
207 device_names.get()->front().device_name, | |
208 device_names.get()->front().unique_id, false); | |
209 | |
210 // Call OnOpen to open using the first device in the list | |
211 OnOpen(capture_params.session_id, device); | |
212 } | |
213 | |
214 VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id); | |
215 if (it == devices_.end()) { | |
216 // Invalid session id | |
217 video_capture_receiver->OnError(); | |
218 return; | |
219 } | |
220 media::VideoCaptureDevice* video_capture_device = it->second; | |
221 | |
222 // Possible errors are signaled to video_capture_receiver by | |
223 // video_capture_device. video_capture_receiver to perform actions. | |
224 video_capture_device->Allocate(capture_params.width, capture_params.height, | |
225 capture_params.frame_per_second, | |
226 video_capture_receiver); | |
227 video_capture_device->Start(); | |
228 } | |
229 | |
230 void VideoCaptureManager::OnStop( | |
231 const media::VideoCaptureSessionId capture_session_id, | |
232 Task* stopped_task) { | |
233 DCHECK(IsOnCaptureDeviceThread()); | |
234 | |
235 VideoCaptureDevices::iterator it = devices_.find(capture_session_id); | |
236 if (it != devices_.end()) { | |
237 media::VideoCaptureDevice* video_capture_device = it->second; | |
238 // Possible errors are signaled to video_capture_receiver by | |
239 // video_capture_device. video_capture_receiver to perform actions. | |
240 video_capture_device->Stop(); | |
241 video_capture_device->DeAllocate(); | |
242 } | |
243 | |
244 if (stopped_task) { | |
245 stopped_task->Run(); | |
246 delete stopped_task; | |
247 } | |
248 | |
249 if (capture_session_id == kStartOpenSessionId) { | |
250 // This device was opened from Start(), not Open(). Close it! | |
251 OnClose(capture_session_id); | |
252 } | |
253 } | |
254 | |
255 void VideoCaptureManager::OnOpened( | |
256 MediaCaptureSessionId capture_session_id) { | |
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
258 if (listener_ == NULL) { | |
259 // Listener has been removed | |
260 return; | |
261 } | |
262 listener_->Opened(kVideoCapture, capture_session_id); | |
263 } | |
264 | |
265 void VideoCaptureManager::OnClosed( | |
266 MediaCaptureSessionId capture_session_id) { | |
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
268 if (listener_ == NULL) { | |
269 // Listener has been removed | |
270 return; | |
271 } | |
272 listener_->Closed(kVideoCapture, capture_session_id); | |
273 } | |
274 | |
275 void VideoCaptureManager::OnDevicesEnumerated( | |
276 const MediaCaptureDevices& devices) { | |
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
278 if (listener_ == NULL) { | |
279 // Listener has been removed | |
280 return; | |
281 } | |
282 listener_->DevicesEnumerated(kVideoCapture, devices); | |
283 } | |
284 | |
285 void VideoCaptureManager::OnError(MediaCaptureSessionId capture_session_id, | |
286 MediaStreamProviderError error) { | |
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
288 if (listener_ == NULL) { | |
289 // Listener has been removed | |
290 return; | |
291 } | |
292 listener_->Error(kVideoCapture, capture_session_id, error); | |
293 } | |
294 | |
295 void VideoCaptureManager::PostOnOpened( | |
296 MediaCaptureSessionId capture_session_id) { | |
297 DCHECK(IsOnCaptureDeviceThread()); | |
298 BrowserThread::PostTask(BrowserThread::IO, | |
299 FROM_HERE, | |
300 NewRunnableMethod(this, | |
301 &VideoCaptureManager::OnOpened, | |
302 capture_session_id)); | |
303 } | |
304 | |
305 void VideoCaptureManager::PostOnClosed( | |
306 MediaCaptureSessionId capture_session_id) { | |
307 DCHECK(IsOnCaptureDeviceThread()); | |
308 BrowserThread::PostTask(BrowserThread::IO, | |
309 FROM_HERE, | |
310 NewRunnableMethod(this, | |
311 &VideoCaptureManager::OnClosed, | |
312 capture_session_id)); | |
313 } | |
314 | |
315 void VideoCaptureManager::PostOnDevicesEnumerated(MediaCaptureDevices devices) { | |
316 DCHECK(IsOnCaptureDeviceThread()); | |
317 | |
318 BrowserThread::PostTask(BrowserThread::IO, | |
319 FROM_HERE, | |
320 NewRunnableMethod( | |
321 this, | |
322 &VideoCaptureManager::OnDevicesEnumerated, | |
323 devices)); | |
324 } | |
325 | |
326 void VideoCaptureManager::PostOnError(MediaCaptureSessionId capture_session_id, | |
327 MediaStreamProviderError error) { | |
328 // Don't check thread here, can be called from both IO thread and device | |
329 // thread. | |
330 BrowserThread::PostTask(BrowserThread::IO, | |
331 FROM_HERE, | |
332 NewRunnableMethod(this, | |
333 &VideoCaptureManager::OnError, | |
334 capture_session_id, | |
335 error)); | |
336 } | |
337 | |
338 bool VideoCaptureManager::IsOnCaptureDeviceThread() const { | |
339 return MessageLoop::current() == vc_device_thread_.message_loop(); | |
340 } | |
341 | |
342 void VideoCaptureManager::GetAvailableDevices( | |
343 media::VideoCaptureDevice::Names* device_names) { | |
344 DCHECK(IsOnCaptureDeviceThread()); | |
345 | |
346 if (!use_fake_device_) { | |
347 media::VideoCaptureDevice::GetDeviceNames(device_names); | |
348 } else { | |
349 media::FakeVideoCaptureDevice::GetDeviceNames(device_names); | |
350 } | |
351 } | |
352 | |
353 bool VideoCaptureManager::DeviceOpened( | |
354 const media::VideoCaptureDevice::Name& device_name) { | |
355 DCHECK(IsOnCaptureDeviceThread()); | |
356 | |
357 for (VideoCaptureDevices::iterator it = devices_.begin(); | |
358 it != devices_.end(); | |
359 ++it) { | |
360 if (device_name.unique_id == it->second->device_name().unique_id) { | |
361 // We've found the device! | |
362 return true; | |
363 } | |
364 } | |
365 return false; | |
366 } | |
367 | |
368 bool VideoCaptureManager::DeviceOpened( | |
369 const MediaCaptureDeviceInfo& device_info) { | |
370 DCHECK(IsOnCaptureDeviceThread()); | |
371 | |
372 for (VideoCaptureDevices::iterator it = devices_.begin(); | |
373 it != devices_.end(); | |
374 it++) { | |
375 if (device_info.device_id == it->second->device_name().unique_id) { | |
376 return true; | |
377 } | |
378 } | |
379 return false; | |
380 } | |
381 | |
382 } // namespace media | |
OLD | NEW |