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/browser/renderer_host/media/audio_input_device_manager.h" | 5 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" |
10 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
11 #include "build/build_config.h" | 12 #include "build/build_config.h" |
12 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
13 #include "content/public/common/media_stream_request.h" | 14 #include "content/public/common/media_stream_request.h" |
14 #include "media/audio/audio_input_ipc.h" | 15 #include "media/audio/audio_input_ipc.h" |
15 #include "media/audio/audio_manager_base.h" | 16 #include "media/audio/audio_manager_base.h" |
16 #include "media/base/audio_parameters.h" | 17 #include "media/base/audio_parameters.h" |
17 #include "media/base/channel_layout.h" | 18 #include "media/base/channel_layout.h" |
| 19 #include "media/base/media_switches.h" |
18 | 20 |
19 #if defined(OS_CHROMEOS) | 21 #if defined(OS_CHROMEOS) |
20 #include "chromeos/audio/cras_audio_handler.h" | 22 #include "chromeos/audio/cras_audio_handler.h" |
21 #endif | 23 #endif |
22 | 24 |
23 namespace content { | 25 namespace content { |
24 | 26 |
25 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; | 27 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; |
26 | 28 |
27 namespace { | 29 namespace { |
28 // Starting id for the first capture session. | 30 // Starting id for the first capture session. |
29 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; | 31 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; |
30 } | 32 } |
31 | 33 |
32 AudioInputDeviceManager::AudioInputDeviceManager( | 34 AudioInputDeviceManager::AudioInputDeviceManager( |
33 media::AudioManager* audio_manager) | 35 media::AudioManager* audio_manager) |
34 : listener_(NULL), | 36 : listener_(NULL), |
35 next_capture_session_id_(kFirstSessionId), | 37 next_capture_session_id_(kFirstSessionId), |
36 use_fake_device_(false), | |
37 #if defined(OS_CHROMEOS) | 38 #if defined(OS_CHROMEOS) |
38 keyboard_mic_streams_count_(0), | 39 keyboard_mic_streams_count_(0), |
39 #endif | 40 #endif |
40 audio_manager_(audio_manager) { | 41 audio_manager_(audio_manager) { |
41 } | 42 } |
42 | 43 |
43 AudioInputDeviceManager::~AudioInputDeviceManager() { | 44 AudioInputDeviceManager::~AudioInputDeviceManager() { |
44 } | 45 } |
45 | 46 |
46 const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById( | 47 const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById( |
(...skipping 14 matching lines...) Expand all Loading... |
61 DCHECK(!device_task_runner_.get()); | 62 DCHECK(!device_task_runner_.get()); |
62 listener_ = listener; | 63 listener_ = listener; |
63 device_task_runner_ = device_task_runner; | 64 device_task_runner_ = device_task_runner; |
64 } | 65 } |
65 | 66 |
66 void AudioInputDeviceManager::Unregister() { | 67 void AudioInputDeviceManager::Unregister() { |
67 DCHECK(listener_); | 68 DCHECK(listener_); |
68 listener_ = NULL; | 69 listener_ = NULL; |
69 } | 70 } |
70 | 71 |
71 void AudioInputDeviceManager::EnumerateDevices(MediaStreamType stream_type) { | |
72 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
73 DCHECK(listener_); | |
74 | |
75 device_task_runner_->PostTask( | |
76 FROM_HERE, | |
77 base::Bind(&AudioInputDeviceManager::EnumerateOnDeviceThread, | |
78 this, stream_type)); | |
79 } | |
80 | |
81 int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) { | 72 int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) { |
82 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 73 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
83 // Generate a new id for this device. | 74 // Generate a new id for this device. |
84 int session_id = next_capture_session_id_++; | 75 int session_id = next_capture_session_id_++; |
85 device_task_runner_->PostTask( | 76 device_task_runner_->PostTask( |
86 FROM_HERE, | 77 FROM_HERE, |
87 base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread, | 78 base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread, |
88 this, session_id, device)); | 79 this, session_id, device)); |
89 | 80 |
90 return session_id; | 81 return session_id; |
(...skipping 10 matching lines...) Expand all Loading... |
101 devices_.erase(device); | 92 devices_.erase(device); |
102 | 93 |
103 // Post a callback through the listener on IO thread since | 94 // Post a callback through the listener on IO thread since |
104 // MediaStreamManager is expecting the callback asynchronously. | 95 // MediaStreamManager is expecting the callback asynchronously. |
105 BrowserThread::PostTask(BrowserThread::IO, | 96 BrowserThread::PostTask(BrowserThread::IO, |
106 FROM_HERE, | 97 FROM_HERE, |
107 base::Bind(&AudioInputDeviceManager::ClosedOnIOThread, | 98 base::Bind(&AudioInputDeviceManager::ClosedOnIOThread, |
108 this, stream_type, session_id)); | 99 this, stream_type, session_id)); |
109 } | 100 } |
110 | 101 |
111 void AudioInputDeviceManager::UseFakeDevice() { | |
112 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
113 use_fake_device_ = true; | |
114 } | |
115 | |
116 bool AudioInputDeviceManager::ShouldUseFakeDevice() const { | |
117 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
118 return use_fake_device_; | |
119 } | |
120 | |
121 #if defined(OS_CHROMEOS) | 102 #if defined(OS_CHROMEOS) |
122 void AudioInputDeviceManager::RegisterKeyboardMicStream( | 103 void AudioInputDeviceManager::RegisterKeyboardMicStream( |
123 const base::Closure& callback) { | 104 const base::Closure& callback) { |
124 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 105 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
125 | 106 |
126 ++keyboard_mic_streams_count_; | 107 ++keyboard_mic_streams_count_; |
127 if (keyboard_mic_streams_count_ == 1) { | 108 if (keyboard_mic_streams_count_ == 1) { |
128 BrowserThread::PostTaskAndReply( | 109 BrowserThread::PostTaskAndReply( |
129 BrowserThread::UI, | 110 BrowserThread::UI, |
130 FROM_HERE, | 111 FROM_HERE, |
(...skipping 17 matching lines...) Expand all Loading... |
148 BrowserThread::UI, | 129 BrowserThread::UI, |
149 FROM_HERE, | 130 FROM_HERE, |
150 base::Bind( | 131 base::Bind( |
151 &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread, | 132 &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread, |
152 this, | 133 this, |
153 false)); | 134 false)); |
154 } | 135 } |
155 } | 136 } |
156 #endif | 137 #endif |
157 | 138 |
158 void AudioInputDeviceManager::EnumerateOnDeviceThread( | |
159 MediaStreamType stream_type) { | |
160 SCOPED_UMA_HISTOGRAM_TIMER( | |
161 "Media.AudioInputDeviceManager.EnumerateOnDeviceThreadTime"); | |
162 DCHECK(IsOnDeviceThread()); | |
163 DCHECK_EQ(MEDIA_DEVICE_AUDIO_CAPTURE, stream_type); | |
164 | |
165 media::AudioDeviceNames device_names; | |
166 if (use_fake_device_) { | |
167 // Use the fake devices. | |
168 GetFakeDeviceNames(&device_names); | |
169 } else { | |
170 // Enumerate the devices on the OS. | |
171 // AudioManager is guaranteed to outlive MediaStreamManager in | |
172 // BrowserMainloop. | |
173 audio_manager_->GetAudioInputDeviceNames(&device_names); | |
174 } | |
175 | |
176 std::unique_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray()); | |
177 for (media::AudioDeviceNames::iterator it = device_names.begin(); | |
178 it != device_names.end(); ++it) { | |
179 // Add device information to device vector. | |
180 devices->emplace_back(stream_type, it->device_name, it->unique_id, | |
181 audio_manager_->GetGroupIDInput(it->unique_id)); | |
182 } | |
183 | |
184 // Return the device list through the listener by posting a task on | |
185 // IO thread since MediaStreamManager handles the callback asynchronously. | |
186 BrowserThread::PostTask( | |
187 BrowserThread::IO, | |
188 FROM_HERE, | |
189 base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread, | |
190 this, stream_type, base::Passed(&devices))); | |
191 } | |
192 | |
193 void AudioInputDeviceManager::OpenOnDeviceThread( | 139 void AudioInputDeviceManager::OpenOnDeviceThread( |
194 int session_id, const StreamDeviceInfo& info) { | 140 int session_id, const StreamDeviceInfo& info) { |
195 SCOPED_UMA_HISTOGRAM_TIMER( | 141 SCOPED_UMA_HISTOGRAM_TIMER( |
196 "Media.AudioInputDeviceManager.OpenOnDeviceThreadTime"); | 142 "Media.AudioInputDeviceManager.OpenOnDeviceThreadTime"); |
197 DCHECK(IsOnDeviceThread()); | 143 DCHECK(IsOnDeviceThread()); |
198 | 144 |
199 StreamDeviceInfo out(info.device.type, info.device.name, info.device.id, | 145 StreamDeviceInfo out(info.device.type, info.device.name, info.device.id, |
200 info.device.group_id, 0, 0, 0); | 146 info.device.group_id, 0, 0, 0); |
201 out.session_id = session_id; | 147 out.session_id = session_id; |
202 | 148 |
203 MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input; | 149 MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input; |
204 | 150 |
205 if (use_fake_device_) { | 151 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 152 switches::kUseFakeDeviceForMediaStream)) { |
206 // Don't need to query the hardware information if using fake device. | 153 // Don't need to query the hardware information if using fake device. |
207 input_params.sample_rate = 44100; | 154 input_params.sample_rate = 44100; |
208 input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO; | 155 input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO; |
209 } else { | 156 } else { |
210 // Get the preferred sample rate and channel configuration for the | 157 // Get the preferred sample rate and channel configuration for the |
211 // audio device. | 158 // audio device. |
212 media::AudioParameters params = | 159 media::AudioParameters params = |
213 audio_manager_->GetInputStreamParameters(info.device.id); | 160 audio_manager_->GetInputStreamParameters(info.device.id); |
214 input_params.sample_rate = params.sample_rate(); | 161 input_params.sample_rate = params.sample_rate(); |
215 input_params.channel_layout = params.channel_layout(); | 162 input_params.channel_layout = params.channel_layout(); |
(...skipping 17 matching lines...) Expand all Loading... |
233 } | 180 } |
234 | 181 |
235 // Return the |session_id| through the listener by posting a task on | 182 // Return the |session_id| through the listener by posting a task on |
236 // IO thread since MediaStreamManager handles the callback asynchronously. | 183 // IO thread since MediaStreamManager handles the callback asynchronously. |
237 BrowserThread::PostTask(BrowserThread::IO, | 184 BrowserThread::PostTask(BrowserThread::IO, |
238 FROM_HERE, | 185 FROM_HERE, |
239 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, | 186 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, |
240 this, session_id, out)); | 187 this, session_id, out)); |
241 } | 188 } |
242 | 189 |
243 void AudioInputDeviceManager::DevicesEnumeratedOnIOThread( | |
244 MediaStreamType stream_type, | |
245 std::unique_ptr<StreamDeviceInfoArray> devices) { | |
246 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
247 // Ensure that |devices| gets deleted on exit. | |
248 if (listener_) | |
249 listener_->DevicesEnumerated(stream_type, *devices); | |
250 } | |
251 | |
252 void AudioInputDeviceManager::OpenedOnIOThread(int session_id, | 190 void AudioInputDeviceManager::OpenedOnIOThread(int session_id, |
253 const StreamDeviceInfo& info) { | 191 const StreamDeviceInfo& info) { |
254 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 192 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
255 DCHECK_EQ(session_id, info.session_id); | 193 DCHECK_EQ(session_id, info.session_id); |
256 DCHECK(GetDevice(session_id) == devices_.end()); | 194 DCHECK(GetDevice(session_id) == devices_.end()); |
257 | 195 |
258 devices_.push_back(info); | 196 devices_.push_back(info); |
259 | 197 |
260 if (listener_) | 198 if (listener_) |
261 listener_->Opened(info.device.type, session_id); | 199 listener_->Opened(info.device.type, session_id); |
(...skipping 14 matching lines...) Expand all Loading... |
276 AudioInputDeviceManager::GetDevice(int session_id) { | 214 AudioInputDeviceManager::GetDevice(int session_id) { |
277 for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end(); | 215 for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end(); |
278 ++i) { | 216 ++i) { |
279 if (i->session_id == session_id) | 217 if (i->session_id == session_id) |
280 return i; | 218 return i; |
281 } | 219 } |
282 | 220 |
283 return devices_.end(); | 221 return devices_.end(); |
284 } | 222 } |
285 | 223 |
286 void AudioInputDeviceManager::GetFakeDeviceNames( | |
287 media::AudioDeviceNames* device_names) { | |
288 static const char kFakeDeviceName1[] = "Fake Audio 1"; | |
289 static const char kFakeDeviceId1[] = "fake_audio_1"; | |
290 static const char kFakeDeviceName2[] = "Fake Audio 2"; | |
291 static const char kFakeDeviceId2[] = "fake_audio_2"; | |
292 DCHECK(device_names->empty()); | |
293 DCHECK(use_fake_device_); | |
294 device_names->push_back(media::AudioDeviceName(kFakeDeviceName1, | |
295 kFakeDeviceId1)); | |
296 device_names->push_back(media::AudioDeviceName(kFakeDeviceName2, | |
297 kFakeDeviceId2)); | |
298 } | |
299 | |
300 #if defined(OS_CHROMEOS) | 224 #if defined(OS_CHROMEOS) |
301 void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread( | 225 void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread( |
302 bool active) { | 226 bool active) { |
303 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 227 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
304 chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active); | 228 chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active); |
305 } | 229 } |
306 #endif | 230 #endif |
307 | 231 |
308 | 232 |
309 } // namespace content | 233 } // namespace content |
OLD | NEW |