Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: content/browser/media_stream/video_capture_manager.cc

Issue 6946001: VideoCaptureManager opens/closes, starts/stops and enumerates video capture devices. VideoCapture... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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
15 enum { kFirstSessionId = 1};
16
17 static ::base::LazyInstance<VideoCaptureManager> g_video_capture_manager(
18 base::LINKER_INITIALIZED);
19
20 bool VideoCaptureManager::use_fake_device_ = false;
21
22 VideoCaptureManager* VideoCaptureManager::Get() {
23 return g_video_capture_manager.Pointer();
24 }
25
26 void VideoCaptureManager::CreateTestManager() {
27 VideoCaptureManager* vcm = g_video_capture_manager.Pointer();
28 vcm->UseFakeDevice();
29 }
30
31 VideoCaptureManager::VideoCaptureManager()
32 : vc_device_thread_("VideoCaptureManagerThread"),
33 listener_(NULL),
34 new_capture_session_id_(kFirstSessionId),
35 devices_() {
36 vc_device_thread_.Start();
37 }
38
39 VideoCaptureManager::~VideoCaptureManager() {
40 vc_device_thread_.Stop();
41 devices_.clear();
42 }
43
44 int VideoCaptureManager::Register(MediaStreamType service_type,
45 MediaStreamProviderListener* listener) {
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
47 if (service_type != kVideoCapture) {
48 // Not a valid service type
49 return -1;
50 }
51 if (listener_) {
52 // Already registered, unregister first.
53 return -1;
54 }
55 listener_ = listener;
56 return 0;
57 }
58
59 void VideoCaptureManager::Unregister(MediaStreamType service_type,
60 MediaStreamProviderListener* listener) {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
62 if (service_type != kVideoCapture) {
63 return;
64 }
65 listener_ = NULL;
66 return;
67 }
68
69 void VideoCaptureManager::EnumerateDevices(MediaStreamType service_type) {
70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
71 if (listener_ == NULL) {
72 return;
73 }
74 if (service_type != kVideoCapture) {
75 PostOnError(-1, kInvalidMediaStreamType);
76 return;
77 }
78
79 vc_device_thread_.message_loop()->PostTask(
80 FROM_HERE,
81 NewRunnableMethod(this,
82 &VideoCaptureManager::OnEnumerateDevices));
83 return;
84 }
85
86 MediaCaptureSessionId VideoCaptureManager::Open(
87 MediaStreamType service_type, const MediaCaptureDeviceInfo& device) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
89 if (listener_ == NULL) {
90 return -1;
91 }
92 if (service_type != kVideoCapture) {
93 PostOnError(-1, kInvalidMediaStreamType);
94 return -1;
95 }
96
97 // Generate a new id for this device
98 MediaCaptureSessionId video_capture_session_id = new_capture_session_id_++;
99
100 vc_device_thread_.message_loop()->PostTask(
101 FROM_HERE,
102 NewRunnableMethod(this,
103 &VideoCaptureManager::OnOpen,
104 video_capture_session_id,
105 device));
106
107 return video_capture_session_id;
108 }
109
110 void VideoCaptureManager::Close(MediaStreamType service_type,
111 MediaCaptureSessionId capture_session_id) {
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
113 if (listener_ == NULL) {
114 return;
115 }
116 if (service_type != kVideoCapture) {
117 PostOnError(-1, kInvalidMediaStreamType);
118 return;
119 }
120
121 vc_device_thread_.message_loop()->PostTask(
122 FROM_HERE,
123 NewRunnableMethod(this,
124 &VideoCaptureManager::OnClose,
125 capture_session_id));
126 return;
127 }
128
129 void VideoCaptureManager::Start(
130 const media::VideoCaptureParams& capture_params,
131 media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
133
134 vc_device_thread_.message_loop()->PostTask(
135 FROM_HERE,
136 NewRunnableMethod(this,
137 &VideoCaptureManager::OnStart,
138 capture_params,
139 video_capture_receiver));
140 }
141
142 void VideoCaptureManager::Stop(
143 const media::VideoCaptureSessionId capture_session_id, Task* stopped_task) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
145
146 vc_device_thread_.message_loop()->PostTask(
147 FROM_HERE,
148 NewRunnableMethod(this,
149 &VideoCaptureManager::OnStop,
150 capture_session_id,
151 stopped_task));
152 }
153
154 void VideoCaptureManager::OnEnumerateDevices() {
155 DCHECK(IsOnCaptureDeviceThread());
156
157 scoped_ptr<media::VideoCaptureDevice::Names> device_names(
158 new media::VideoCaptureDevice::Names());
159 GetAvailableDevices(device_names.get());
160
161 MediaCaptureDevices devices;
162 for (media::VideoCaptureDevice::Names::iterator it =
163 device_names.get()->begin(); it != device_names.get()->end(); ++it) {
wjia(left Chromium) 2011/05/06 00:11:31 one more space indent
mflodman1 2011/05/06 11:52:38 What is the indent-rule here? I thought it was 4 s
164 bool opened = DeviceOpened(*it);
165 devices.push_back(MediaCaptureDeviceInfo(kVideoCapture, it->device_name,
166 it->unique_id, opened));
167 }
168
169 // Let the listener know the result
170 PostOnDevicesEnumerated(devices);
171
172 // Clean-up
173 devices.clear();
174 device_names.get()->clear();
175
176 return;
177 }
178
179 void VideoCaptureManager::OnOpen(MediaCaptureSessionId capture_session_id,
180 const MediaCaptureDeviceInfo device) {
181 DCHECK(IsOnCaptureDeviceThread());
182 if (devices_.find(capture_session_id) != devices_.end()) {
183 // id already exists!
184 PostOnError(capture_session_id, kInvalidSession);
185 return;
186 }
187
188 // Check if another session has already opened this device, only one user per
189 // device is supported.
wjia(left Chromium) 2011/05/06 00:11:31 looks like you can use DeviceOpened() here.
mflodman1 2011/05/06 11:52:38 DeviceOpened has a different input type, but I cre
190 for (VideoCaptureDevices::iterator it = devices_.begin();
191 it != devices_.end();
192 it++) {
193 media::VideoCaptureDevice* vc_device = it->second;
194 if (vc_device != NULL) {
wjia(left Chromium) 2011/05/06 00:11:31 if vc_device == NULL here, is it an error?
mflodman1 2011/05/06 11:52:38 Removed. vc_device == null only if a device can't
195 if (device.device_id.compare(vc_device->device_name().unique_id) == 0) {
196 PostOnError(capture_session_id, kDeviceAlreadyInUse);
197 return;
198 }
199 }
200 }
201
202 // Open the device
203 media::VideoCaptureDevice::Name vc_device_name;
204 vc_device_name.device_name = device.name;
205 vc_device_name.unique_id = device.device_id;
206
207 media::VideoCaptureDevice* video_capture_device = NULL;
208 if (!use_fake_device_) {
209 video_capture_device = media::VideoCaptureDevice::Create(vc_device_name);
210 } else {
211 video_capture_device =
212 media::FakeVideoCaptureDevice::Create(vc_device_name);
213 }
214 if (video_capture_device == NULL) {
215 PostOnError(capture_session_id, kDeviceNotAvailable);
216 return;
217 }
218
219 devices_[capture_session_id] = video_capture_device;
220 PostOnOpened(capture_session_id);
221 return;
222 }
223
224 void VideoCaptureManager::OnClose(
225 MediaCaptureSessionId capture_session_id) {
226 DCHECK(IsOnCaptureDeviceThread());
227 if (devices_.find(capture_session_id) == devices_.end()) {
228 return;
229 }
230
231 VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
232 if (it == devices_.end()) {
233 // Device not opened
234 PostOnClosed(capture_session_id);
235 return;
236 }
237 // Deallocate (if not done already) and delete the device
238 media::VideoCaptureDevice* video_capture_device = it->second;
239 video_capture_device->DeAllocate();
240 delete video_capture_device;
241 devices_.erase(it);
242
243 PostOnClosed(capture_session_id);
244 return;
245 }
246
247 void VideoCaptureManager::OnStart(
248 const media::VideoCaptureParams capture_params,
249 media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
250 DCHECK(IsOnCaptureDeviceThread());
251
252 // Solution for not using MediaStreamManager
253 // This session id won't be returned by Open()
254 if (capture_params.session_id == kStartOpenSessionId) {
255 // Start() is called without using Open(), we need to open a device
256 scoped_ptr<media::VideoCaptureDevice::Names> device_names(
257 new media::VideoCaptureDevice::Names());
258 GetAvailableDevices(device_names.get());
259
260 MediaCaptureDeviceInfo device(kVideoCapture,
261 device_names.get()->front().device_name,
262 device_names.get()->front().unique_id, false);
263
264 // Call OnOpen to open using the first device in the list
265 OnOpen(capture_params.session_id, device);
266 device_names.get()->clear();
wjia(left Chromium) 2011/05/06 00:11:31 clear() is not needed. scoped_ptr should take care
mflodman1 2011/05/06 11:52:38 Done.
267 }
268
269 VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id);
270 if (it == devices_.end()) {
271 // Invalid session id
272 video_capture_receiver->OnError();
273 return;
274 }
275 media::VideoCaptureDevice* video_capture_device = it->second;
276
277 // Possible errors are signaled to host
wjia(left Chromium) 2011/05/06 00:11:31 comment doesn't match.
mflodman1 2011/05/06 11:52:38 Comment updated.
278 video_capture_device->Allocate(capture_params.width, capture_params.height,
279 capture_params.frame_per_second,
280 video_capture_receiver);
281 video_capture_device->Start();
282 return;
283 }
284
285 void VideoCaptureManager::OnStop(
286 const media::VideoCaptureSessionId capture_session_id,
287 Task* stopped_task) {
288 DCHECK(IsOnCaptureDeviceThread());
289
290 VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
291 if (it != devices_.end()) {
292 media::VideoCaptureDevice* video_capture_device = it->second;
293 // Possible errors are signaled by video_capture_device
wjia(left Chromium) 2011/05/06 00:11:31 comment doesn't match.
mflodman1 2011/05/06 11:52:38 Comment updated.
294 video_capture_device->Stop();
295 video_capture_device->DeAllocate();
296 }
297
298 if (stopped_task) {
299 stopped_task->Run();
300 delete stopped_task;
301 }
302
303 if (capture_session_id == kStartOpenSessionId) {
304 // This device was opened from Start(), not Open(). Close it!
305 OnClose(capture_session_id);
306 }
307 return;
308 }
309
310 void VideoCaptureManager::OnOpened(
311 MediaCaptureSessionId capture_session_id) {
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
313 if (listener_ == NULL) {
314 // Listener has been removed
315 return;
316 }
317 listener_->Opened(kVideoCapture, capture_session_id);
318 return;
319 }
320
321 void VideoCaptureManager::OnClosed(
322 MediaCaptureSessionId capture_session_id) {
323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
324 if (listener_ == NULL) {
325 // Listener has been removed
326 return;
327 }
328 listener_->Closed(kVideoCapture, capture_session_id);
329 return;
330 }
331
332 void VideoCaptureManager::OnDevicesEnumerated(
333 const MediaCaptureDevices& devices) {
334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
335 if (listener_ == NULL) {
336 // Listener has been removed
337 return;
338 }
339 listener_->DevicesEnumerated(kVideoCapture, devices);
340 return;
341 }
342
343 void VideoCaptureManager::OnError(MediaCaptureSessionId capture_session_id,
344 MediaStreamProviderError error) {
345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
346 if (listener_ == NULL) {
347 // Listener has been removed
348 return;
349 }
350 listener_->Error(kVideoCapture, capture_session_id, error);
351 return;
352 }
353
354 void VideoCaptureManager::PostOnOpened(
355 MediaCaptureSessionId capture_session_id) {
356 DCHECK(IsOnCaptureDeviceThread());
357
358 BrowserThread::PostTask(BrowserThread::IO,
359 FROM_HERE,
360 NewRunnableFunction(
361 &VideoCaptureManager::OnOpenedProxy,
362 capture_session_id));
wjia(left Chromium) 2011/05/06 00:11:31 there is no need for On*Proxy. You can use: Bro
mflodman1 2011/05/06 11:52:38 Done.
363 return;
364 }
365
366 void VideoCaptureManager::PostOnClosed(
367 MediaCaptureSessionId capture_session_id) {
368 DCHECK(IsOnCaptureDeviceThread());
369 BrowserThread::PostTask(BrowserThread::IO,
370 FROM_HERE,
371 NewRunnableFunction(
372 &VideoCaptureManager::OnClosedProxy,
373 capture_session_id));
374 return;
375 }
376
377 void VideoCaptureManager::PostOnDevicesEnumerated(
378 const MediaCaptureDevices& devices) {
379 DCHECK(IsOnCaptureDeviceThread());
380 BrowserThread::PostTask(BrowserThread::IO,
381 FROM_HERE,
382 NewRunnableFunction(
383 &VideoCaptureManager::OnDevicesEnumeratedProxy,
384 devices));
385 return;
386 }
387
388 void VideoCaptureManager::PostOnError(MediaCaptureSessionId capture_session_id,
389 MediaStreamProviderError error) {
390 DCHECK(IsOnCaptureDeviceThread());
391 BrowserThread::PostTask(BrowserThread::IO,
392 FROM_HERE,
393 NewRunnableFunction(
394 &VideoCaptureManager::OnErrorProxy,
395 capture_session_id,
396 error));
397 return;
398 }
399
400 void VideoCaptureManager::OnOpenedProxy(
401 MediaCaptureSessionId capture_session_id) {
402 Get()->OnOpened(capture_session_id);
403 }
404
405 void VideoCaptureManager::OnClosedProxy(
406 MediaCaptureSessionId capture_session_id) {
407 Get()->OnClosed(capture_session_id);
408 }
409
410 void VideoCaptureManager::OnDevicesEnumeratedProxy(
411 const MediaCaptureDevices devices) {
412 Get()->OnDevicesEnumerated(devices);
413 }
414
415 void VideoCaptureManager::OnErrorProxy(MediaCaptureSessionId capture_session_id,
416 MediaStreamProviderError error) {
417 Get()->OnError(capture_session_id, error);
418 }
419
420 bool VideoCaptureManager::IsOnCaptureDeviceThread() const {
421 return MessageLoop::current() == vc_device_thread_.message_loop();
422 }
423
424 void VideoCaptureManager::GetAvailableDevices(
425 media::VideoCaptureDevice::Names* device_names) {
426 DCHECK(IsOnCaptureDeviceThread());
427
428 if (!use_fake_device_) {
429 media::VideoCaptureDevice::GetDeviceNames(device_names);
430 } else {
431 media::FakeVideoCaptureDevice::GetDeviceNames(device_names);
432 }
433 return;
434 }
435
436 bool VideoCaptureManager::DeviceOpened(
437 const media::VideoCaptureDevice::Name& device_name) {
438 DCHECK(IsOnCaptureDeviceThread());
439
440 for (VideoCaptureDevices::iterator it = devices_.begin();
441 it != devices_.end();
442 ++it) {
443 if (device_name.unique_id.compare(it->second->device_name().unique_id)
444 == 0 ) {
445 // We've found the device!
446 return true;
447 }
448 }
449 return false;
450 }
451
452 void VideoCaptureManager::UseFakeDevice() {
453 use_fake_device_ = true;
454 }
455
456 MessageLoop* VideoCaptureManager::GetMessageLoop() {
457 return vc_device_thread_.message_loop();
458 }
459
460 } // namespace media
mflodman1 2011/05/05 11:11:22 Will add newline in next upload.
mflodman1 2011/05/06 11:52:38 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698