Chromium Code Reviews| Index: content/browser/renderer_host/media/video_capture_manager.cc |
| =================================================================== |
| --- content/browser/renderer_host/media/video_capture_manager.cc (revision 107671) |
| +++ content/browser/renderer_host/media/video_capture_manager.cc (working copy) |
| @@ -5,8 +5,10 @@ |
| #include "content/browser/renderer_host/media/video_capture_manager.h" |
| #include "base/bind.h" |
| -#include "base/memory/scoped_ptr.h" |
| +#include "base/stl_util.h" |
| #include "content/browser/browser_thread.h" |
| +#include "content/browser/renderer_host/media/video_capture_controller.h" |
| +#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" |
| #include "media/video/capture/fake_video_capture_device.h" |
| #include "media/video/capture/video_capture_device.h" |
| @@ -17,6 +19,21 @@ |
| // explicitly calling open device. |
| enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; |
| +struct VideoCaptureManager::Controller { |
| + Controller( |
| + VideoCaptureController* vc_controller, |
| + VideoCaptureControllerEventHandler* handler) |
| + : controller(vc_controller), |
| + ready_to_delete(false) { |
| + handlers.push_front(handler); |
| + } |
| + ~Controller() {} |
| + |
| + scoped_refptr<VideoCaptureController> controller; |
| + bool ready_to_delete; |
| + Handlers handlers; |
| +}; |
| + |
| VideoCaptureManager::VideoCaptureManager() |
| : vc_device_thread_("VideoCaptureManagerThread"), |
| listener_(NULL), |
| @@ -38,6 +55,7 @@ |
| it->second->DeAllocate(); |
| delete it->second; |
| } |
| + STLDeleteValues(&controllers_); |
| } |
| void VideoCaptureManager::Register(MediaStreamProviderListener* listener) { |
| @@ -193,32 +211,17 @@ |
| DCHECK(IsOnCaptureDeviceThread()); |
| DCHECK(video_capture_receiver != NULL); |
| - // Solution for not using MediaStreamManager. |
| - // This session id won't be returned by Open(). |
| - if (capture_params.session_id == kStartOpenSessionId) { |
| - // Start() is called without using Open(), we need to open a device. |
| - media::VideoCaptureDevice::Names device_names; |
| - GetAvailableDevices(&device_names); |
| - if (device_names.empty()) { |
| - // No devices available. |
| - video_capture_receiver->OnError(); |
| - return; |
| - } |
| - StreamDeviceInfo device(kVideoCapture, |
| - device_names.front().device_name, |
| - device_names.front().unique_id, false); |
| - |
| - // Call OnOpen to open using the first device in the list. |
| - OnOpen(capture_params.session_id, device); |
| - } |
| - |
| - VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id); |
| - if (it == devices_.end()) { |
| + media::VideoCaptureDevice* video_capture_device = |
| + GetDeviceInternal(capture_params.session_id); |
| + if (!video_capture_device) { |
| // Invalid session id. |
| video_capture_receiver->OnError(); |
| return; |
| } |
| - media::VideoCaptureDevice* video_capture_device = it->second; |
| + Controllers::iterator cit = controllers_.find(video_capture_device); |
| + if (cit != controllers_.end()) { |
| + cit->second->ready_to_delete = false; |
| + } |
| // Possible errors are signaled to video_capture_receiver by |
| // video_capture_device. video_capture_receiver to perform actions. |
| @@ -240,6 +243,14 @@ |
| // video_capture_device. video_capture_receiver to perform actions. |
| video_capture_device->Stop(); |
| video_capture_device->DeAllocate(); |
| + Controllers::iterator cit = controllers_.find(video_capture_device); |
| + if (cit != controllers_.end()) { |
| + cit->second->ready_to_delete = true; |
| + if (cit->second->handlers.size() == 0) { |
|
scherkus (not reviewing)
2011/10/31 03:20:18
.empty()
wjia(left Chromium)
2011/10/31 22:02:44
Done.
|
| + delete cit->second; |
| + controllers_.erase(cit); |
| + } |
| + } |
| } |
| if (!stopped_cb.is_null()) |
| @@ -370,4 +381,106 @@ |
| return false; |
| } |
| +void VideoCaptureManager::AddController( |
| + const media::VideoCaptureParams& capture_params, |
| + VideoCaptureControllerEventHandler* handler, |
| + base::Callback<void(VideoCaptureController*)> added_cb) { |
| + DCHECK(handler); |
| + vc_device_thread_.message_loop()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread, |
| + base::Unretained(this), capture_params, handler, added_cb)); |
| +} |
| + |
| +void VideoCaptureManager::DoAddControllerOnDeviceThread( |
| + const media::VideoCaptureParams capture_params, |
| + VideoCaptureControllerEventHandler* handler, |
| + base::Callback<void(VideoCaptureController*)> added_cb) { |
| + DCHECK(IsOnCaptureDeviceThread()); |
| + |
| + media::VideoCaptureDevice* video_capture_device = |
| + GetDeviceInternal(capture_params.session_id); |
| + scoped_refptr<VideoCaptureController> ctrller = NULL; |
| + if (video_capture_device) { |
| + Controllers::iterator cit = controllers_.find(video_capture_device); |
| + if (cit == controllers_.end()) { |
| + ctrller = new VideoCaptureController(this); |
|
scherkus (not reviewing)
2011/10/31 03:20:18
try to avoid abbreviations -- can we use |controll
wjia(left Chromium)
2011/10/31 22:02:44
Done.
|
| + controllers_[video_capture_device] = new Controller(ctrller, handler); |
| + } else { |
| + controllers_[video_capture_device]->handlers.push_front(handler); |
| + ctrller = controllers_[video_capture_device]->controller; |
| + } |
| + } |
| + added_cb.Run(ctrller); |
| +} |
| + |
| +void VideoCaptureManager::RemoveController( |
| + VideoCaptureController* controller, |
| + VideoCaptureControllerEventHandler* handler) { |
| + DCHECK(handler); |
| + vc_device_thread_.message_loop()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread, |
| + base::Unretained(this), |
| + make_scoped_refptr(controller), |
| + handler)); |
| +} |
| + |
| +void VideoCaptureManager::DoRemoveControllerOnDeviceThread( |
| + VideoCaptureController* controller, |
| + VideoCaptureControllerEventHandler* handler) { |
| + DCHECK(IsOnCaptureDeviceThread()); |
| + |
| + for (Controllers::iterator cit = controllers_.begin(); |
| + cit != controllers_.end(); ++cit) { |
| + if (controller == cit->second->controller) { |
| + Handlers& handlers = cit->second->handlers; |
| + for (Handlers::iterator hit = handlers.begin(); |
| + hit != handlers.end(); ++hit) { |
| + if ((*hit) == handler) { |
| + handlers.erase(hit); |
| + break; |
| + } |
| + } |
| + if (handlers.size() == 0 && cit->second->ready_to_delete) { |
| + delete cit->second; |
| + controllers_.erase(cit); |
| + } |
| + return; |
| + } |
| + } |
| +} |
| + |
| +media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal( |
| + int capture_session_id) { |
| + DCHECK(IsOnCaptureDeviceThread()); |
| + VideoCaptureDevices::iterator dit = devices_.find(capture_session_id); |
| + if (dit != devices_.end()) { |
| + return dit->second; |
| + } |
| + |
| + // Solution for not using MediaStreamManager. |
| + // This session id won't be returned by Open(). |
| + if (capture_session_id == kStartOpenSessionId) { |
| + media::VideoCaptureDevice::Names device_names; |
| + GetAvailableDevices(&device_names); |
| + if (device_names.empty()) { |
| + // No devices available. |
| + return NULL; |
| + } |
| + StreamDeviceInfo device(kVideoCapture, |
| + device_names.front().device_name, |
| + device_names.front().unique_id, false); |
| + |
| + // Call OnOpen to open using the first device in the list. |
| + OnOpen(capture_session_id, device); |
| + |
| + VideoCaptureDevices::iterator dit = devices_.find(capture_session_id); |
| + if (dit != devices_.end()) { |
| + return dit->second; |
| + } |
| + } |
| + return NULL; |
| +} |
| + |
| } // namespace media_stream |