Add ICU message format support
[chromium-blink-merge.git] / content / renderer / media / video_capture_impl_manager.cc
bloba7c8deb947d37260db3aeaca1875ce74e8ebe8b7
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
3 // found in the LICENSE file.
4 //
5 // Implementation notes about interactions with VideoCaptureImpl.
6 //
7 // How is VideoCaptureImpl used:
8 //
9 // VideoCaptureImpl is an IO thread object while VideoCaptureImplManager
10 // lives only on the render thread. It is only possible to access an
11 // object of VideoCaptureImpl via a task on the IO thread.
13 // How is VideoCaptureImpl deleted:
15 // A task is posted to the IO thread to delete a VideoCaptureImpl.
16 // Immediately after that the pointer to it is dropped. This means no
17 // access to this VideoCaptureImpl object is possible on the render
18 // thread. Also note that VideoCaptureImpl does not post task to itself.
20 // The use of Unretained:
22 // We make sure deletion is the last task on the IO thread for a
23 // VideoCaptureImpl object. This allows the use of Unretained() binding.
25 #include "content/renderer/media/video_capture_impl_manager.h"
27 #include "base/bind.h"
28 #include "base/bind_helpers.h"
29 #include "base/location.h"
30 #include "base/thread_task_runner_handle.h"
31 #include "content/child/child_process.h"
32 #include "content/renderer/media/video_capture_impl.h"
33 #include "content/renderer/media/video_capture_message_filter.h"
34 #include "media/base/bind_to_current_loop.h"
36 namespace content {
38 VideoCaptureImplManager::VideoCaptureImplManager()
39 : next_client_id_(0),
40 filter_(new VideoCaptureMessageFilter()),
41 render_main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
42 weak_factory_(this) {
45 VideoCaptureImplManager::~VideoCaptureImplManager() {
46 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
47 if (devices_.empty())
48 return;
49 // Forcibly release all video capture resources.
50 for (const auto& device : devices_) {
51 VideoCaptureImpl* const impl = device.second.second;
52 ChildProcess::current()->io_task_runner()->PostTask(
53 FROM_HERE,
54 base::Bind(&VideoCaptureImpl::DeInit, base::Unretained(impl)));
55 ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE, impl);
57 devices_.clear();
60 base::Closure VideoCaptureImplManager::UseDevice(
61 media::VideoCaptureSessionId id) {
62 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
64 VideoCaptureImpl* impl = NULL;
65 const VideoCaptureDeviceMap::iterator it = devices_.find(id);
66 if (it == devices_.end()) {
67 impl = CreateVideoCaptureImplForTesting(id, filter_.get());
68 if (!impl)
69 impl = new VideoCaptureImpl(id, filter_.get());
70 devices_[id] = std::make_pair(1, impl);
71 ChildProcess::current()->io_task_runner()->PostTask(
72 FROM_HERE, base::Bind(&VideoCaptureImpl::Init, base::Unretained(impl)));
73 } else {
74 ++it->second.first;
76 return base::Bind(&VideoCaptureImplManager::UnrefDevice,
77 weak_factory_.GetWeakPtr(), id);
80 base::Closure VideoCaptureImplManager::StartCapture(
81 media::VideoCaptureSessionId id,
82 const media::VideoCaptureParams& params,
83 const VideoCaptureStateUpdateCB& state_update_cb,
84 const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
85 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
86 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
87 DCHECK(it != devices_.end());
88 VideoCaptureImpl* const impl = it->second.second;
90 // This ID is used to identify a client of VideoCaptureImpl.
91 const int client_id = ++next_client_id_;
93 ChildProcess::current()->io_task_runner()->PostTask(
94 FROM_HERE,
95 base::Bind(&VideoCaptureImpl::StartCapture, base::Unretained(impl),
96 client_id, params, state_update_cb, deliver_frame_cb));
97 return base::Bind(&VideoCaptureImplManager::StopCapture,
98 weak_factory_.GetWeakPtr(),
99 client_id, id);
102 void VideoCaptureImplManager::GetDeviceSupportedFormats(
103 media::VideoCaptureSessionId id,
104 const VideoCaptureDeviceFormatsCB& callback) {
105 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
106 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
107 DCHECK(it != devices_.end());
108 VideoCaptureImpl* const impl = it->second.second;
109 ChildProcess::current()->io_task_runner()->PostTask(
110 FROM_HERE, base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats,
111 base::Unretained(impl), callback));
114 void VideoCaptureImplManager::GetDeviceFormatsInUse(
115 media::VideoCaptureSessionId id,
116 const VideoCaptureDeviceFormatsCB& callback) {
117 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
118 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
119 DCHECK(it != devices_.end());
120 VideoCaptureImpl* const impl = it->second.second;
121 ChildProcess::current()->io_task_runner()->PostTask(
122 FROM_HERE, base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse,
123 base::Unretained(impl), callback));
126 VideoCaptureImpl*
127 VideoCaptureImplManager::CreateVideoCaptureImplForTesting(
128 media::VideoCaptureSessionId id,
129 VideoCaptureMessageFilter* filter) const {
130 return NULL;
133 void VideoCaptureImplManager::StopCapture(int client_id,
134 media::VideoCaptureSessionId id) {
135 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
136 const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
137 DCHECK(it != devices_.end());
138 VideoCaptureImpl* const impl = it->second.second;
139 ChildProcess::current()->io_task_runner()->PostTask(
140 FROM_HERE, base::Bind(&VideoCaptureImpl::StopCapture,
141 base::Unretained(impl), client_id));
144 void VideoCaptureImplManager::UnrefDevice(
145 media::VideoCaptureSessionId id) {
146 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
147 const VideoCaptureDeviceMap::iterator it = devices_.find(id);
148 DCHECK(it != devices_.end());
149 VideoCaptureImpl* const impl = it->second.second;
151 // Unref and destroy on the IO thread if there's no more client.
152 DCHECK(it->second.first);
153 --it->second.first;
154 if (!it->second.first) {
155 devices_.erase(id);
156 ChildProcess::current()->io_task_runner()->PostTask(
157 FROM_HERE,
158 base::Bind(&VideoCaptureImpl::DeInit, base::Unretained(impl)));
159 ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE, impl);
163 void VideoCaptureImplManager::SuspendDevices(bool suspend) {
164 DCHECK(render_main_task_runner_->BelongsToCurrentThread());
165 for (const auto& device : devices_) {
166 VideoCaptureImpl* const impl = device.second.second;
167 ChildProcess::current()->io_task_runner()->PostTask(
168 FROM_HERE, base::Bind(&VideoCaptureImpl::SuspendCapture,
169 base::Unretained(impl), suspend));
173 } // namespace content