OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/browser/renderer_host/media/video_capture_manager.h" | 5 #include "content/browser/renderer_host/media/video_capture_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/stl_util.h" |
9 #include "content/browser/browser_thread.h" | 9 #include "content/browser/browser_thread.h" |
| 10 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 11 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" |
10 #include "media/video/capture/fake_video_capture_device.h" | 12 #include "media/video/capture/fake_video_capture_device.h" |
11 #include "media/video/capture/video_capture_device.h" | 13 #include "media/video/capture/video_capture_device.h" |
12 | 14 |
13 namespace media_stream { | 15 namespace media_stream { |
14 | 16 |
15 // Starting id for the first capture session. | 17 // Starting id for the first capture session. |
16 // VideoCaptureManager::kStartOpenSessionId is used as default id without | 18 // VideoCaptureManager::kStartOpenSessionId is used as default id without |
17 // explicitly calling open device. | 19 // explicitly calling open device. |
18 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; | 20 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; |
19 | 21 |
| 22 struct VideoCaptureManager::Controller { |
| 23 Controller( |
| 24 VideoCaptureController* vc_controller, |
| 25 VideoCaptureControllerEventHandler* handler) |
| 26 : controller(vc_controller), |
| 27 ready_to_delete(false) { |
| 28 handlers.push_front(handler); |
| 29 } |
| 30 ~Controller() {} |
| 31 |
| 32 scoped_refptr<VideoCaptureController> controller; |
| 33 bool ready_to_delete; |
| 34 Handlers handlers; |
| 35 }; |
| 36 |
20 VideoCaptureManager::VideoCaptureManager() | 37 VideoCaptureManager::VideoCaptureManager() |
21 : vc_device_thread_("VideoCaptureManagerThread"), | 38 : vc_device_thread_("VideoCaptureManagerThread"), |
22 listener_(NULL), | 39 listener_(NULL), |
23 new_capture_session_id_(kFirstSessionId), | 40 new_capture_session_id_(kFirstSessionId), |
24 use_fake_device_(false) { | 41 use_fake_device_(false) { |
25 vc_device_thread_.Start(); | 42 vc_device_thread_.Start(); |
26 } | 43 } |
27 | 44 |
28 VideoCaptureManager::~VideoCaptureManager() { | 45 VideoCaptureManager::~VideoCaptureManager() { |
29 vc_device_thread_.Stop(); | 46 vc_device_thread_.Stop(); |
30 // TODO(mflodman) Remove this temporary solution when shut-down issue is | 47 // TODO(mflodman) Remove this temporary solution when shut-down issue is |
31 // resolved, i.e. all code below this comment. | 48 // resolved, i.e. all code below this comment. |
32 // Temporary solution: close all open devices and delete them, after the | 49 // Temporary solution: close all open devices and delete them, after the |
33 // thread is stopped. | 50 // thread is stopped. |
34 DLOG_IF(ERROR, !devices_.empty()) << "VideoCaptureManager: Open devices!"; | 51 DLOG_IF(ERROR, !devices_.empty()) << "VideoCaptureManager: Open devices!"; |
35 for (VideoCaptureDevices::iterator it = devices_.begin(); | 52 for (VideoCaptureDevices::iterator it = devices_.begin(); |
36 it != devices_.end(); | 53 it != devices_.end(); |
37 ++it) { | 54 ++it) { |
38 it->second->DeAllocate(); | 55 it->second->DeAllocate(); |
39 delete it->second; | 56 delete it->second; |
40 } | 57 } |
| 58 STLDeleteValues(&controllers_); |
41 } | 59 } |
42 | 60 |
43 void VideoCaptureManager::Register(MediaStreamProviderListener* listener) { | 61 void VideoCaptureManager::Register(MediaStreamProviderListener* listener) { |
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
45 DCHECK(!listener_); | 63 DCHECK(!listener_); |
46 listener_ = listener; | 64 listener_ = listener; |
47 } | 65 } |
48 | 66 |
49 void VideoCaptureManager::Unregister() { | 67 void VideoCaptureManager::Unregister() { |
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 | 204 |
187 PostOnClosed(capture_session_id); | 205 PostOnClosed(capture_session_id); |
188 } | 206 } |
189 | 207 |
190 void VideoCaptureManager::OnStart( | 208 void VideoCaptureManager::OnStart( |
191 const media::VideoCaptureParams capture_params, | 209 const media::VideoCaptureParams capture_params, |
192 media::VideoCaptureDevice::EventHandler* video_capture_receiver) { | 210 media::VideoCaptureDevice::EventHandler* video_capture_receiver) { |
193 DCHECK(IsOnCaptureDeviceThread()); | 211 DCHECK(IsOnCaptureDeviceThread()); |
194 DCHECK(video_capture_receiver != NULL); | 212 DCHECK(video_capture_receiver != NULL); |
195 | 213 |
196 // Solution for not using MediaStreamManager. | 214 media::VideoCaptureDevice* video_capture_device = |
197 // This session id won't be returned by Open(). | 215 GetDeviceInternal(capture_params.session_id); |
198 if (capture_params.session_id == kStartOpenSessionId) { | 216 if (!video_capture_device) { |
199 // Start() is called without using Open(), we need to open a device. | |
200 media::VideoCaptureDevice::Names device_names; | |
201 GetAvailableDevices(&device_names); | |
202 if (device_names.empty()) { | |
203 // No devices available. | |
204 video_capture_receiver->OnError(); | |
205 return; | |
206 } | |
207 StreamDeviceInfo device(kVideoCapture, | |
208 device_names.front().device_name, | |
209 device_names.front().unique_id, false); | |
210 | |
211 // Call OnOpen to open using the first device in the list. | |
212 OnOpen(capture_params.session_id, device); | |
213 } | |
214 | |
215 VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id); | |
216 if (it == devices_.end()) { | |
217 // Invalid session id. | 217 // Invalid session id. |
218 video_capture_receiver->OnError(); | 218 video_capture_receiver->OnError(); |
219 return; | 219 return; |
220 } | 220 } |
221 media::VideoCaptureDevice* video_capture_device = it->second; | 221 Controllers::iterator cit = controllers_.find(video_capture_device); |
| 222 if (cit != controllers_.end()) { |
| 223 cit->second->ready_to_delete = false; |
| 224 } |
222 | 225 |
223 // Possible errors are signaled to video_capture_receiver by | 226 // Possible errors are signaled to video_capture_receiver by |
224 // video_capture_device. video_capture_receiver to perform actions. | 227 // video_capture_device. video_capture_receiver to perform actions. |
225 video_capture_device->Allocate(capture_params.width, capture_params.height, | 228 video_capture_device->Allocate(capture_params.width, capture_params.height, |
226 capture_params.frame_per_second, | 229 capture_params.frame_per_second, |
227 video_capture_receiver); | 230 video_capture_receiver); |
228 video_capture_device->Start(); | 231 video_capture_device->Start(); |
229 } | 232 } |
230 | 233 |
231 void VideoCaptureManager::OnStop( | 234 void VideoCaptureManager::OnStop( |
232 const media::VideoCaptureSessionId capture_session_id, | 235 const media::VideoCaptureSessionId capture_session_id, |
233 base::Closure stopped_cb) { | 236 base::Closure stopped_cb) { |
234 DCHECK(IsOnCaptureDeviceThread()); | 237 DCHECK(IsOnCaptureDeviceThread()); |
235 | 238 |
236 VideoCaptureDevices::iterator it = devices_.find(capture_session_id); | 239 VideoCaptureDevices::iterator it = devices_.find(capture_session_id); |
237 if (it != devices_.end()) { | 240 if (it != devices_.end()) { |
238 media::VideoCaptureDevice* video_capture_device = it->second; | 241 media::VideoCaptureDevice* video_capture_device = it->second; |
239 // Possible errors are signaled to video_capture_receiver by | 242 // Possible errors are signaled to video_capture_receiver by |
240 // video_capture_device. video_capture_receiver to perform actions. | 243 // video_capture_device. video_capture_receiver to perform actions. |
241 video_capture_device->Stop(); | 244 video_capture_device->Stop(); |
242 video_capture_device->DeAllocate(); | 245 video_capture_device->DeAllocate(); |
| 246 Controllers::iterator cit = controllers_.find(video_capture_device); |
| 247 if (cit != controllers_.end()) { |
| 248 cit->second->ready_to_delete = true; |
| 249 if (cit->second->handlers.size() == 0) { |
| 250 delete cit->second; |
| 251 controllers_.erase(cit); |
| 252 } |
| 253 } |
243 } | 254 } |
244 | 255 |
245 if (!stopped_cb.is_null()) | 256 if (!stopped_cb.is_null()) |
246 stopped_cb.Run(); | 257 stopped_cb.Run(); |
247 | 258 |
248 if (capture_session_id == kStartOpenSessionId) { | 259 if (capture_session_id == kStartOpenSessionId) { |
249 // This device was opened from Start(), not Open(). Close it! | 260 // This device was opened from Start(), not Open(). Close it! |
250 OnClose(capture_session_id); | 261 OnClose(capture_session_id); |
251 } | 262 } |
252 } | 263 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 for (VideoCaptureDevices::iterator it = devices_.begin(); | 374 for (VideoCaptureDevices::iterator it = devices_.begin(); |
364 it != devices_.end(); | 375 it != devices_.end(); |
365 it++) { | 376 it++) { |
366 if (device_info.device_id == it->second->device_name().unique_id) { | 377 if (device_info.device_id == it->second->device_name().unique_id) { |
367 return true; | 378 return true; |
368 } | 379 } |
369 } | 380 } |
370 return false; | 381 return false; |
371 } | 382 } |
372 | 383 |
| 384 void VideoCaptureManager::AddController( |
| 385 const media::VideoCaptureParams& capture_params, |
| 386 VideoCaptureControllerEventHandler* handler, |
| 387 base::Callback<void(VideoCaptureController*)> added_cb) { |
| 388 DCHECK(handler); |
| 389 vc_device_thread_.message_loop()->PostTask( |
| 390 FROM_HERE, |
| 391 base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread, |
| 392 base::Unretained(this), capture_params, handler, added_cb)); |
| 393 } |
| 394 |
| 395 void VideoCaptureManager::DoAddControllerOnDeviceThread( |
| 396 const media::VideoCaptureParams capture_params, |
| 397 VideoCaptureControllerEventHandler* handler, |
| 398 base::Callback<void(VideoCaptureController*)> added_cb) { |
| 399 DCHECK(IsOnCaptureDeviceThread()); |
| 400 |
| 401 media::VideoCaptureDevice* video_capture_device = |
| 402 GetDeviceInternal(capture_params.session_id); |
| 403 scoped_refptr<VideoCaptureController> ctrller = NULL; |
| 404 if (video_capture_device) { |
| 405 Controllers::iterator cit = controllers_.find(video_capture_device); |
| 406 if (cit == controllers_.end()) { |
| 407 ctrller = new VideoCaptureController(this); |
| 408 controllers_[video_capture_device] = new Controller(ctrller, handler); |
| 409 } else { |
| 410 controllers_[video_capture_device]->handlers.push_front(handler); |
| 411 ctrller = controllers_[video_capture_device]->controller; |
| 412 } |
| 413 } |
| 414 added_cb.Run(ctrller); |
| 415 } |
| 416 |
| 417 void VideoCaptureManager::RemoveController( |
| 418 VideoCaptureController* controller, |
| 419 VideoCaptureControllerEventHandler* handler) { |
| 420 DCHECK(handler); |
| 421 vc_device_thread_.message_loop()->PostTask( |
| 422 FROM_HERE, |
| 423 base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread, |
| 424 base::Unretained(this), |
| 425 make_scoped_refptr(controller), |
| 426 handler)); |
| 427 } |
| 428 |
| 429 void VideoCaptureManager::DoRemoveControllerOnDeviceThread( |
| 430 VideoCaptureController* controller, |
| 431 VideoCaptureControllerEventHandler* handler) { |
| 432 DCHECK(IsOnCaptureDeviceThread()); |
| 433 |
| 434 for (Controllers::iterator cit = controllers_.begin(); |
| 435 cit != controllers_.end(); ++cit) { |
| 436 if (controller == cit->second->controller) { |
| 437 Handlers& handlers = cit->second->handlers; |
| 438 for (Handlers::iterator hit = handlers.begin(); |
| 439 hit != handlers.end(); ++hit) { |
| 440 if ((*hit) == handler) { |
| 441 handlers.erase(hit); |
| 442 break; |
| 443 } |
| 444 } |
| 445 if (handlers.size() == 0 && cit->second->ready_to_delete) { |
| 446 delete cit->second; |
| 447 controllers_.erase(cit); |
| 448 } |
| 449 return; |
| 450 } |
| 451 } |
| 452 } |
| 453 |
| 454 media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal( |
| 455 int capture_session_id) { |
| 456 DCHECK(IsOnCaptureDeviceThread()); |
| 457 VideoCaptureDevices::iterator dit = devices_.find(capture_session_id); |
| 458 if (dit != devices_.end()) { |
| 459 return dit->second; |
| 460 } |
| 461 |
| 462 // Solution for not using MediaStreamManager. |
| 463 // This session id won't be returned by Open(). |
| 464 if (capture_session_id == kStartOpenSessionId) { |
| 465 media::VideoCaptureDevice::Names device_names; |
| 466 GetAvailableDevices(&device_names); |
| 467 if (device_names.empty()) { |
| 468 // No devices available. |
| 469 return NULL; |
| 470 } |
| 471 StreamDeviceInfo device(kVideoCapture, |
| 472 device_names.front().device_name, |
| 473 device_names.front().unique_id, false); |
| 474 |
| 475 // Call OnOpen to open using the first device in the list. |
| 476 OnOpen(capture_session_id, device); |
| 477 |
| 478 VideoCaptureDevices::iterator dit = devices_.find(capture_session_id); |
| 479 if (dit != devices_.end()) { |
| 480 return dit->second; |
| 481 } |
| 482 } |
| 483 return NULL; |
| 484 } |
| 485 |
373 } // namespace media_stream | 486 } // namespace media_stream |
OLD | NEW |