| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/renderer/media/video_capture_impl_manager.h" | 5 #include "content/renderer/media/video_capture_impl_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "content/public/renderer/render_thread.h" |
| 9 #include "content/renderer/media/video_capture_impl.h" | 10 #include "content/renderer/media/video_capture_impl.h" |
| 10 #include "content/renderer/media/video_capture_message_filter.h" | 11 #include "content/renderer/media/video_capture_message_filter.h" |
| 12 #include "media/base/bind_to_current_loop.h" |
| 11 | 13 |
| 12 namespace content { | 14 namespace content { |
| 13 | 15 |
| 14 VideoCaptureImplManager::VideoCaptureImplManager() | 16 VideoCaptureHandle::VideoCaptureHandle( |
| 15 : thread_("VC manager") { | 17 media::VideoCapture* impl, base::Closure destruction_cb) |
| 16 thread_.Start(); | 18 : impl_(impl), destruction_cb_(destruction_cb) { |
| 17 message_loop_proxy_ = thread_.message_loop_proxy(); | |
| 18 filter_ = new VideoCaptureMessageFilter(); | |
| 19 } | 19 } |
| 20 | 20 |
| 21 media::VideoCapture* VideoCaptureImplManager::AddDevice( | 21 VideoCaptureHandle::~VideoCaptureHandle() { |
| 22 media::VideoCaptureSessionId id, | 22 destruction_cb_.Run(); |
| 23 media::VideoCapture::EventHandler* handler) { | 23 } |
| 24 DCHECK(handler); | |
| 25 | 24 |
| 26 base::AutoLock auto_lock(lock_); | 25 void VideoCaptureHandle::StartCapture( |
| 27 Devices::iterator it = devices_.find(id); | 26 EventHandler* handler, |
| 27 const media::VideoCaptureParams& params) { |
| 28 impl_->StartCapture(handler, params); |
| 29 } |
| 30 |
| 31 void VideoCaptureHandle::StopCapture(EventHandler* handler) { |
| 32 impl_->StopCapture(handler); |
| 33 } |
| 34 |
| 35 bool VideoCaptureHandle::CaptureStarted() { |
| 36 return impl_->CaptureStarted(); |
| 37 } |
| 38 |
| 39 int VideoCaptureHandle::CaptureFrameRate() { |
| 40 return impl_->CaptureFrameRate(); |
| 41 } |
| 42 |
| 43 VideoCaptureImplManager::VideoCaptureImplManager() |
| 44 : filter_(new VideoCaptureMessageFilter()), |
| 45 weak_factory_(this) { |
| 46 } |
| 47 |
| 48 VideoCaptureImplManager::~VideoCaptureImplManager() { |
| 49 DCHECK(thread_checker_.CalledOnValidThread()); |
| 50 } |
| 51 |
| 52 scoped_ptr<VideoCaptureHandle> VideoCaptureImplManager::UseDevice( |
| 53 media::VideoCaptureSessionId id) { |
| 54 DCHECK(thread_checker_.CalledOnValidThread()); |
| 55 |
| 56 VideoCaptureImpl* video_capture_device = NULL; |
| 57 VideoCaptureDeviceMap::iterator it = devices_.find(id); |
| 28 if (it == devices_.end()) { | 58 if (it == devices_.end()) { |
| 29 VideoCaptureImpl* vc = | 59 video_capture_device = CreateVideoCaptureImpl(id, filter_.get()); |
| 30 new VideoCaptureImpl(id, message_loop_proxy_.get(), filter_.get()); | 60 devices_[id] = |
| 31 devices_[id] = new Device(vc, handler); | 61 std::make_pair(1, linked_ptr<VideoCaptureImpl>(video_capture_device)); |
| 32 vc->Init(); | 62 video_capture_device->Init(); |
| 33 return vc; | 63 } else { |
| 64 ++it->second.first; |
| 65 video_capture_device = it->second.second.get(); |
| 34 } | 66 } |
| 35 | 67 |
| 36 devices_[id]->clients.push_front(handler); | 68 // This callback ensures UnrefDevice() happens on the render thread. |
| 37 return it->second->vc; | 69 return scoped_ptr<VideoCaptureHandle>( |
| 70 new VideoCaptureHandle( |
| 71 video_capture_device, |
| 72 media::BindToCurrentLoop( |
| 73 base::Bind( |
| 74 &VideoCaptureImplManager::UnrefDevice, |
| 75 weak_factory_.GetWeakPtr(), |
| 76 id)))); |
| 77 } |
| 78 |
| 79 VideoCaptureImpl* VideoCaptureImplManager::CreateVideoCaptureImpl( |
| 80 media::VideoCaptureSessionId id, |
| 81 VideoCaptureMessageFilter* filter) const { |
| 82 return new VideoCaptureImpl(id, filter); |
| 83 } |
| 84 |
| 85 void VideoCaptureImplManager::UnrefDevice( |
| 86 media::VideoCaptureSessionId id) { |
| 87 DCHECK(thread_checker_.CalledOnValidThread()); |
| 88 VideoCaptureDeviceMap::iterator it = devices_.find(id); |
| 89 DCHECK(it != devices_.end()); |
| 90 |
| 91 DCHECK(it->second.first); |
| 92 --it->second.first; |
| 93 if (!it->second.first) { |
| 94 VideoCaptureImpl* impl = it->second.second.release(); |
| 95 devices_.erase(id); |
| 96 impl->DeInit(base::Bind(&base::DeletePointer<VideoCaptureImpl>, impl)); |
| 97 } |
| 38 } | 98 } |
| 39 | 99 |
| 40 void VideoCaptureImplManager::SuspendDevices(bool suspend) { | 100 void VideoCaptureImplManager::SuspendDevices(bool suspend) { |
| 41 base::AutoLock auto_lock(lock_); | 101 DCHECK(thread_checker_.CalledOnValidThread()); |
| 42 for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) | 102 for (VideoCaptureDeviceMap::iterator it = devices_.begin(); |
| 43 it->second->vc->SuspendCapture(suspend); | 103 it != devices_.end(); ++it) |
| 104 it->second.second->SuspendCapture(suspend); |
| 44 } | 105 } |
| 45 | 106 |
| 46 void VideoCaptureImplManager::RemoveDevice( | |
| 47 media::VideoCaptureSessionId id, | |
| 48 media::VideoCapture::EventHandler* handler) { | |
| 49 DCHECK(handler); | |
| 50 | |
| 51 base::AutoLock auto_lock(lock_); | |
| 52 Devices::iterator it = devices_.find(id); | |
| 53 if (it == devices_.end()) | |
| 54 return; | |
| 55 | |
| 56 size_t size = it->second->clients.size(); | |
| 57 it->second->clients.remove(handler); | |
| 58 | |
| 59 if (size == it->second->clients.size() || size > 1) | |
| 60 return; | |
| 61 | |
| 62 devices_[id]->vc->DeInit(base::Bind(&VideoCaptureImplManager::FreeDevice, | |
| 63 this, devices_[id]->vc)); | |
| 64 delete devices_[id]; | |
| 65 devices_.erase(id); | |
| 66 } | |
| 67 | |
| 68 void VideoCaptureImplManager::FreeDevice(VideoCaptureImpl* vc) { | |
| 69 delete vc; | |
| 70 } | |
| 71 | |
| 72 VideoCaptureImplManager::~VideoCaptureImplManager() { | |
| 73 thread_.Stop(); | |
| 74 // TODO(wjia): uncomment the line below after collecting enough info for | |
| 75 // crbug.com/152418. | |
| 76 // STLDeleteContainerPairSecondPointers(devices_.begin(), devices_.end()); | |
| 77 } | |
| 78 | |
| 79 VideoCaptureImplManager::Device::Device( | |
| 80 VideoCaptureImpl* device, | |
| 81 media::VideoCapture::EventHandler* handler) | |
| 82 : vc(device) { | |
| 83 clients.push_front(handler); | |
| 84 } | |
| 85 | |
| 86 VideoCaptureImplManager::Device::~Device() {} | |
| 87 | |
| 88 } // namespace content | 107 } // namespace content |
| OLD | NEW |