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 "media/audio/audio_manager_base.h" | 5 #include "media/audio/audio_manager_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
10 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 | 25 |
26 // Default maximum number of input streams that can be open simultaneously | 26 // Default maximum number of input streams that can be open simultaneously |
27 // for all platforms. | 27 // for all platforms. |
28 static const int kDefaultMaxInputStreams = 16; | 28 static const int kDefaultMaxInputStreams = 16; |
29 | 29 |
30 static const int kMaxInputChannels = 2; | 30 static const int kMaxInputChannels = 2; |
31 | 31 |
32 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 32 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
33 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 33 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
34 | 34 |
35 struct AudioManagerBase::DispatcherParams { | |
36 DispatcherParams(const AudioParameters& input, | |
37 const AudioParameters& output, | |
38 const std::string& device_id) | |
39 : input_params(input), | |
40 output_params(output), | |
41 input_device_id(device_id) {} | |
42 ~DispatcherParams() {} | |
43 | |
44 const AudioParameters input_params; | |
45 const AudioParameters output_params; | |
46 const std::string input_device_id; | |
47 scoped_refptr<AudioOutputDispatcher> dispatcher; | |
48 | |
49 private: | |
50 DISALLOW_COPY_AND_ASSIGN(DispatcherParams); | |
51 }; | |
52 | |
53 class AudioManagerBase::CompareByParams { | |
54 public: | |
55 explicit CompareByParams(const DispatcherParams* dispatcher) | |
56 : dispatcher_(dispatcher) {} | |
57 bool operator()(DispatcherParams* dispatcher_in) const { | |
58 // We will reuse the existing dispatcher when: | |
59 // 1) Unified IO is not used, input_params and output_params of the | |
60 // existing dispatcher are the same as the requested dispatcher. | |
61 // 2) Unified IO is used, input_params, output_params and input_device_id | |
62 // of the existing dispatcher are the same as the request dispatcher. | |
63 return (dispatcher_->input_params == dispatcher_in->input_params && | |
64 dispatcher_->output_params == dispatcher_in->output_params && | |
65 (!dispatcher_->input_params.input_channels() || | |
66 dispatcher_->input_device_id == dispatcher_in->input_device_id)); | |
67 } | |
68 | |
69 private: | |
70 const DispatcherParams* dispatcher_; | |
71 }; | |
72 | |
35 AudioManagerBase::AudioManagerBase() | 73 AudioManagerBase::AudioManagerBase() |
36 : num_active_input_streams_(0), | 74 : num_active_input_streams_(0), |
37 max_num_output_streams_(kDefaultMaxOutputStreams), | 75 max_num_output_streams_(kDefaultMaxOutputStreams), |
38 max_num_input_streams_(kDefaultMaxInputStreams), | 76 max_num_input_streams_(kDefaultMaxInputStreams), |
39 num_output_streams_(0), | 77 num_output_streams_(0), |
40 num_input_streams_(0), | 78 num_input_streams_(0), |
41 output_listeners_( | 79 output_listeners_( |
42 ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), | 80 ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), |
43 audio_thread_(new base::Thread("AudioThread")) { | 81 audio_thread_(new base::Thread("AudioThread")) { |
44 #if defined(OS_WIN) | 82 #if defined(OS_WIN) |
(...skipping 25 matching lines...) Expand all Loading... | |
70 | 108 |
71 string16 AudioManagerBase::GetAudioInputDeviceModel() { | 109 string16 AudioManagerBase::GetAudioInputDeviceModel() { |
72 return string16(); | 110 return string16(); |
73 } | 111 } |
74 | 112 |
75 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { | 113 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { |
76 return message_loop_; | 114 return message_loop_; |
77 } | 115 } |
78 | 116 |
79 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( | 117 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( |
80 const AudioParameters& params) { | 118 const AudioParameters& params, |
119 const std::string& input_device_id) { | |
81 // TODO(miu): Fix ~50 call points across several unit test modules to call | 120 // TODO(miu): Fix ~50 call points across several unit test modules to call |
82 // this method on the audio thread, then uncomment the following: | 121 // this method on the audio thread, then uncomment the following: |
83 // DCHECK(message_loop_->BelongsToCurrentThread()); | 122 // DCHECK(message_loop_->BelongsToCurrentThread()); |
84 | 123 |
85 if (!params.IsValid()) { | 124 if (!params.IsValid()) { |
86 DLOG(ERROR) << "Audio parameters are invalid"; | 125 DLOG(ERROR) << "Audio parameters are invalid"; |
87 return NULL; | 126 return NULL; |
88 } | 127 } |
89 | 128 |
90 // Limit the number of audio streams opened. This is to prevent using | 129 // Limit the number of audio streams opened. This is to prevent using |
91 // excessive resources for a large number of audio streams. More | 130 // excessive resources for a large number of audio streams. More |
92 // importantly it prevents instability on certain systems. | 131 // importantly it prevents instability on certain systems. |
93 // See bug: http://crbug.com/30242. | 132 // See bug: http://crbug.com/30242. |
94 if (num_output_streams_ >= max_num_output_streams_) { | 133 if (num_output_streams_ >= max_num_output_streams_) { |
95 DLOG(ERROR) << "Number of opened output audio streams " | 134 DLOG(ERROR) << "Number of opened output audio streams " |
96 << num_output_streams_ | 135 << num_output_streams_ |
97 << " exceed the max allowed number " | 136 << " exceed the max allowed number " |
98 << max_num_output_streams_; | 137 << max_num_output_streams_; |
99 return NULL; | 138 return NULL; |
100 } | 139 } |
101 | 140 |
102 AudioOutputStream* stream; | 141 AudioOutputStream* stream; |
103 switch (params.format()) { | 142 switch (params.format()) { |
104 case AudioParameters::AUDIO_PCM_LINEAR: | 143 case AudioParameters::AUDIO_PCM_LINEAR: |
105 stream = MakeLinearOutputStream(params); | 144 stream = MakeLinearOutputStream(params); |
106 break; | 145 break; |
107 case AudioParameters::AUDIO_PCM_LOW_LATENCY: | 146 case AudioParameters::AUDIO_PCM_LOW_LATENCY: |
108 stream = MakeLowLatencyOutputStream(params); | 147 stream = MakeLowLatencyOutputStream(params, input_device_id); |
109 break; | 148 break; |
110 case AudioParameters::AUDIO_FAKE: | 149 case AudioParameters::AUDIO_FAKE: |
111 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 150 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
112 break; | 151 break; |
113 default: | 152 default: |
114 stream = NULL; | 153 stream = NULL; |
115 break; | 154 break; |
116 } | 155 } |
117 | 156 |
118 if (stream) { | 157 if (stream) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 } | 197 } |
159 | 198 |
160 if (stream) { | 199 if (stream) { |
161 ++num_input_streams_; | 200 ++num_input_streams_; |
162 } | 201 } |
163 | 202 |
164 return stream; | 203 return stream; |
165 } | 204 } |
166 | 205 |
167 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 206 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
168 const AudioParameters& params) { | 207 const AudioParameters& params, const std::string& input_device_id) { |
169 #if defined(OS_IOS) | 208 #if defined(OS_IOS) |
170 // IOS implements audio input only. | 209 // IOS implements audio input only. |
171 NOTIMPLEMENTED(); | 210 NOTIMPLEMENTED(); |
172 return NULL; | 211 return NULL; |
173 #else | 212 #else |
174 DCHECK(message_loop_->BelongsToCurrentThread()); | 213 DCHECK(message_loop_->BelongsToCurrentThread()); |
175 | 214 |
176 // If we're not using AudioOutputResampler our output parameters are the same | 215 // If we're not using AudioOutputResampler our output parameters are the same |
177 // as our input parameters. | 216 // as our input parameters. |
178 AudioParameters output_params = params; | 217 AudioParameters output_params = params; |
(...skipping 13 matching lines...) Expand all Loading... | |
192 << output_params.frames_per_buffer(); | 231 << output_params.frames_per_buffer(); |
193 | 232 |
194 // Tell the AudioManager to create a fake output device. | 233 // Tell the AudioManager to create a fake output device. |
195 output_params = AudioParameters( | 234 output_params = AudioParameters( |
196 AudioParameters::AUDIO_FAKE, params.channel_layout(), | 235 AudioParameters::AUDIO_FAKE, params.channel_layout(), |
197 params.sample_rate(), params.bits_per_sample(), | 236 params.sample_rate(), params.bits_per_sample(), |
198 params.frames_per_buffer()); | 237 params.frames_per_buffer()); |
199 } | 238 } |
200 } | 239 } |
201 | 240 |
202 std::pair<AudioParameters, AudioParameters> dispatcher_key = | 241 DispatcherParams* dispatcher_params = |
203 std::make_pair(params, output_params); | 242 new DispatcherParams(params, output_params, input_device_id); |
204 AudioOutputDispatchersMap::iterator it = | 243 |
205 output_dispatchers_.find(dispatcher_key); | 244 AudioOutputDispatchers::iterator it = |
206 if (it != output_dispatchers_.end()) | 245 std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(), |
207 return new AudioOutputProxy(it->second.get()); | 246 CompareByParams(dispatcher_params)); |
247 if (it != output_dispatchers_.end()) { | |
248 delete dispatcher_params; | |
249 return new AudioOutputProxy((*it)->dispatcher); | |
250 } | |
208 | 251 |
209 const base::TimeDelta kCloseDelay = | 252 const base::TimeDelta kCloseDelay = |
210 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds); | 253 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds); |
211 | 254 |
212 if (output_params.format() != AudioParameters::AUDIO_FAKE) { | 255 if (output_params.format() != AudioParameters::AUDIO_FAKE) { |
213 scoped_refptr<AudioOutputDispatcher> dispatcher = | 256 scoped_refptr<AudioOutputDispatcher> dispatcher = |
214 new AudioOutputResampler(this, params, output_params, kCloseDelay); | 257 new AudioOutputResampler(this, params, output_params, input_device_id, |
215 output_dispatchers_[dispatcher_key] = dispatcher; | 258 kCloseDelay); |
259 dispatcher_params->dispatcher = dispatcher; | |
216 return new AudioOutputProxy(dispatcher.get()); | 260 return new AudioOutputProxy(dispatcher.get()); |
Jeffrey Yasskin
2013/08/07 23:00:47
This leaks the dispatcher_params. What did you mea
no longer working on chromium
2013/08/08 08:35:00
Oh, thanks for finding it out, I am making a CL to
| |
217 } | 261 } |
218 | 262 |
219 scoped_refptr<AudioOutputDispatcher> dispatcher = | 263 scoped_refptr<AudioOutputDispatcher> dispatcher = |
220 new AudioOutputDispatcherImpl(this, output_params, kCloseDelay); | 264 new AudioOutputDispatcherImpl(this, output_params, input_device_id, |
221 output_dispatchers_[dispatcher_key] = dispatcher; | 265 kCloseDelay); |
266 dispatcher_params->dispatcher = dispatcher; | |
267 output_dispatchers_.push_back(dispatcher_params); | |
222 return new AudioOutputProxy(dispatcher.get()); | 268 return new AudioOutputProxy(dispatcher.get()); |
223 #endif // defined(OS_IOS) | 269 #endif // defined(OS_IOS) |
224 } | 270 } |
225 | 271 |
226 void AudioManagerBase::ShowAudioInputSettings() { | 272 void AudioManagerBase::ShowAudioInputSettings() { |
227 } | 273 } |
228 | 274 |
229 void AudioManagerBase::GetAudioInputDeviceNames( | 275 void AudioManagerBase::GetAudioInputDeviceNames( |
230 media::AudioDeviceNames* device_names) { | 276 media::AudioDeviceNames* device_names) { |
231 } | 277 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 | 331 |
286 void AudioManagerBase::ShutdownOnAudioThread() { | 332 void AudioManagerBase::ShutdownOnAudioThread() { |
287 // IOS implements audio input only. | 333 // IOS implements audio input only. |
288 #if defined(OS_IOS) | 334 #if defined(OS_IOS) |
289 return; | 335 return; |
290 #else | 336 #else |
291 // This should always be running on the audio thread, but since we've cleared | 337 // This should always be running on the audio thread, but since we've cleared |
292 // the audio_thread_ member pointer when we get here, we can't verify exactly | 338 // the audio_thread_ member pointer when we get here, we can't verify exactly |
293 // what thread we're running on. The method is not public though and only | 339 // what thread we're running on. The method is not public though and only |
294 // called from one place, so we'll leave it at that. | 340 // called from one place, so we'll leave it at that. |
295 AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin(); | 341 AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); |
296 for (; it != output_dispatchers_.end(); ++it) { | 342 for (; it != output_dispatchers_.end(); ++it) { |
297 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second; | 343 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher; |
298 if (dispatcher.get()) { | 344 if (dispatcher.get()) { |
299 dispatcher->Shutdown(); | 345 dispatcher->Shutdown(); |
300 // All AudioOutputProxies must have been freed before Shutdown is called. | 346 // All AudioOutputProxies must have been freed before Shutdown is called. |
301 // If they still exist, things will go bad. They have direct pointers to | 347 // If they still exist, things will go bad. They have direct pointers to |
302 // both physical audio stream objects that belong to the dispatcher as | 348 // both physical audio stream objects that belong to the dispatcher as |
303 // well as the message loop of the audio thread that will soon go away. | 349 // well as the message loop of the audio thread that will soon go away. |
304 // So, better crash now than later. | 350 // So, better crash now than later. |
305 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; | 351 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; |
306 dispatcher = NULL; | 352 dispatcher = NULL; |
307 } | 353 } |
(...skipping 25 matching lines...) Expand all Loading... | |
333 return GetPreferredOutputStreamParameters(AudioParameters()); | 379 return GetPreferredOutputStreamParameters(AudioParameters()); |
334 } | 380 } |
335 | 381 |
336 AudioParameters AudioManagerBase::GetInputStreamParameters( | 382 AudioParameters AudioManagerBase::GetInputStreamParameters( |
337 const std::string& device_id) { | 383 const std::string& device_id) { |
338 NOTREACHED(); | 384 NOTREACHED(); |
339 return AudioParameters(); | 385 return AudioParameters(); |
340 } | 386 } |
341 | 387 |
342 } // namespace media | 388 } // namespace media |
OLD | NEW |