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

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: Small change to unit test mock version of listener. 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 = 2};
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) {
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698