| 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/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 static const int kMaxInputChannels = 2; | 31 static const int kMaxInputChannels = 2; |
| 32 | 32 |
| 33 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 33 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
| 34 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 34 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
| 35 const char AudioManagerBase::kLoopbackInputDeviceId[] = "loopback"; | 35 const char AudioManagerBase::kLoopbackInputDeviceId[] = "loopback"; |
| 36 | 36 |
| 37 struct AudioManagerBase::DispatcherParams { | 37 struct AudioManagerBase::DispatcherParams { |
| 38 DispatcherParams(const AudioParameters& input, | 38 DispatcherParams(const AudioParameters& input, |
| 39 const AudioParameters& output, | 39 const AudioParameters& output, |
| 40 const std::string& output_device_id, | 40 const std::string& output_device_id) |
| 41 const std::string& input_device_id) | |
| 42 : input_params(input), | 41 : input_params(input), |
| 43 output_params(output), | 42 output_params(output) {} |
| 44 input_device_id(input_device_id), | |
| 45 output_device_id(output_device_id) {} | |
| 46 ~DispatcherParams() {} | 43 ~DispatcherParams() {} |
| 47 | 44 |
| 48 const AudioParameters input_params; | 45 const AudioParameters input_params; |
| 49 const AudioParameters output_params; | 46 const AudioParameters output_params; |
| 50 const std::string input_device_id; | |
| 51 const std::string output_device_id; | 47 const std::string output_device_id; |
| 52 scoped_refptr<AudioOutputDispatcher> dispatcher; | 48 scoped_refptr<AudioOutputDispatcher> dispatcher; |
| 53 | 49 |
| 54 private: | 50 private: |
| 55 DISALLOW_COPY_AND_ASSIGN(DispatcherParams); | 51 DISALLOW_COPY_AND_ASSIGN(DispatcherParams); |
| 56 }; | 52 }; |
| 57 | 53 |
| 58 class AudioManagerBase::CompareByParams { | 54 class AudioManagerBase::CompareByParams { |
| 59 public: | 55 public: |
| 60 explicit CompareByParams(const DispatcherParams* dispatcher) | 56 explicit CompareByParams(const DispatcherParams* dispatcher) |
| 61 : dispatcher_(dispatcher) {} | 57 : dispatcher_(dispatcher) {} |
| 62 bool operator()(DispatcherParams* dispatcher_in) const { | 58 bool operator()(DispatcherParams* dispatcher_in) const { |
| 63 // We will reuse the existing dispatcher when: | 59 // We will reuse the existing dispatcher when: |
| 64 // 1) Unified IO is not used, input_params and output_params of the | 60 // 1) Unified IO is not used, input_params and output_params of the |
| 65 // existing dispatcher are the same as the requested dispatcher. | 61 // existing dispatcher are the same as the requested dispatcher. |
| 66 // 2) Unified IO is used, input_params, output_params and input_device_id | 62 // 2) Unified IO is used, input_params and output_params of the existing |
| 67 // of the existing dispatcher are the same as the request dispatcher. | 63 // dispatcher are the same as the request dispatcher. |
| 68 return (dispatcher_->input_params == dispatcher_in->input_params && | 64 return (dispatcher_->input_params == dispatcher_in->input_params && |
| 69 dispatcher_->output_params == dispatcher_in->output_params && | 65 dispatcher_->output_params == dispatcher_in->output_params && |
| 70 dispatcher_->output_device_id == dispatcher_in->output_device_id && | 66 dispatcher_->output_device_id == dispatcher_in->output_device_id); |
| 71 (!dispatcher_->input_params.input_channels() || | |
| 72 dispatcher_->input_device_id == dispatcher_in->input_device_id)); | |
| 73 } | 67 } |
| 74 | 68 |
| 75 private: | 69 private: |
| 76 const DispatcherParams* dispatcher_; | 70 const DispatcherParams* dispatcher_; |
| 77 }; | 71 }; |
| 78 | 72 |
| 79 AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory) | 73 AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory) |
| 80 : max_num_output_streams_(kDefaultMaxOutputStreams), | 74 : max_num_output_streams_(kDefaultMaxOutputStreams), |
| 81 max_num_input_streams_(kDefaultMaxInputStreams), | 75 max_num_input_streams_(kDefaultMaxInputStreams), |
| 82 num_output_streams_(0), | 76 num_output_streams_(0), |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 AudioManagerBase::GetWorkerTaskRunner() { | 126 AudioManagerBase::GetWorkerTaskRunner() { |
| 133 // Lazily start the worker thread. | 127 // Lazily start the worker thread. |
| 134 if (!audio_thread_.IsRunning()) | 128 if (!audio_thread_.IsRunning()) |
| 135 CHECK(audio_thread_.Start()); | 129 CHECK(audio_thread_.Start()); |
| 136 | 130 |
| 137 return audio_thread_.message_loop_proxy(); | 131 return audio_thread_.message_loop_proxy(); |
| 138 } | 132 } |
| 139 | 133 |
| 140 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( | 134 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( |
| 141 const AudioParameters& params, | 135 const AudioParameters& params, |
| 142 const std::string& device_id, | 136 const std::string& device_id) { |
| 143 const std::string& input_device_id) { | |
| 144 // TODO(miu): Fix ~50 call points across several unit test modules to call | 137 // TODO(miu): Fix ~50 call points across several unit test modules to call |
| 145 // this method on the audio thread, then uncomment the following: | 138 // this method on the audio thread, then uncomment the following: |
| 146 // DCHECK(task_runner_->BelongsToCurrentThread()); | 139 // DCHECK(task_runner_->BelongsToCurrentThread()); |
| 147 | 140 |
| 148 if (!params.IsValid()) { | 141 if (!params.IsValid()) { |
| 149 DLOG(ERROR) << "Audio parameters are invalid"; | 142 DLOG(ERROR) << "Audio parameters are invalid"; |
| 150 return NULL; | 143 return NULL; |
| 151 } | 144 } |
| 152 | 145 |
| 153 // Limit the number of audio streams opened. This is to prevent using | 146 // Limit the number of audio streams opened. This is to prevent using |
| 154 // excessive resources for a large number of audio streams. More | 147 // excessive resources for a large number of audio streams. More |
| 155 // importantly it prevents instability on certain systems. | 148 // importantly it prevents instability on certain systems. |
| 156 // See bug: http://crbug.com/30242. | 149 // See bug: http://crbug.com/30242. |
| 157 if (num_output_streams_ >= max_num_output_streams_) { | 150 if (num_output_streams_ >= max_num_output_streams_) { |
| 158 DLOG(ERROR) << "Number of opened output audio streams " | 151 DLOG(ERROR) << "Number of opened output audio streams " |
| 159 << num_output_streams_ | 152 << num_output_streams_ |
| 160 << " exceed the max allowed number " | 153 << " exceed the max allowed number " |
| 161 << max_num_output_streams_; | 154 << max_num_output_streams_; |
| 162 return NULL; | 155 return NULL; |
| 163 } | 156 } |
| 164 | 157 |
| 165 AudioOutputStream* stream; | 158 AudioOutputStream* stream; |
| 166 switch (params.format()) { | 159 switch (params.format()) { |
| 167 case AudioParameters::AUDIO_PCM_LINEAR: | 160 case AudioParameters::AUDIO_PCM_LINEAR: |
| 168 DCHECK(device_id.empty()) | 161 DCHECK(device_id.empty()) |
| 169 << "AUDIO_PCM_LINEAR supports only the default device."; | 162 << "AUDIO_PCM_LINEAR supports only the default device."; |
| 170 stream = MakeLinearOutputStream(params); | 163 stream = MakeLinearOutputStream(params); |
| 171 break; | 164 break; |
| 172 case AudioParameters::AUDIO_PCM_LOW_LATENCY: | 165 case AudioParameters::AUDIO_PCM_LOW_LATENCY: |
| 173 stream = MakeLowLatencyOutputStream(params, device_id, input_device_id); | 166 stream = MakeLowLatencyOutputStream(params, device_id); |
| 174 break; | 167 break; |
| 175 case AudioParameters::AUDIO_FAKE: | 168 case AudioParameters::AUDIO_FAKE: |
| 176 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 169 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
| 177 break; | 170 break; |
| 178 default: | 171 default: |
| 179 stream = NULL; | 172 stream = NULL; |
| 180 break; | 173 break; |
| 181 } | 174 } |
| 182 | 175 |
| 183 if (stream) { | 176 if (stream) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 | 218 |
| 226 if (stream) { | 219 if (stream) { |
| 227 ++num_input_streams_; | 220 ++num_input_streams_; |
| 228 } | 221 } |
| 229 | 222 |
| 230 return stream; | 223 return stream; |
| 231 } | 224 } |
| 232 | 225 |
| 233 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( | 226 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
| 234 const AudioParameters& params, | 227 const AudioParameters& params, |
| 235 const std::string& device_id, | 228 const std::string& device_id) { |
| 236 const std::string& input_device_id) { | |
| 237 DCHECK(task_runner_->BelongsToCurrentThread()); | 229 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 238 | 230 |
| 239 // If the caller supplied an empty device id to select the default device, | 231 // If the caller supplied an empty device id to select the default device, |
| 240 // we fetch the actual device id of the default device so that the lookup | 232 // we fetch the actual device id of the default device so that the lookup |
| 241 // will find the correct device regardless of whether it was opened as | 233 // will find the correct device regardless of whether it was opened as |
| 242 // "default" or via the specific id. | 234 // "default" or via the specific id. |
| 243 // NOTE: Implementations that don't yet support opening non-default output | 235 // NOTE: Implementations that don't yet support opening non-default output |
| 244 // devices may return an empty string from GetDefaultOutputDeviceID(). | 236 // devices may return an empty string from GetDefaultOutputDeviceID(). |
| 245 std::string output_device_id = device_id.empty() ? | 237 std::string output_device_id = device_id.empty() ? |
| 246 GetDefaultOutputDeviceID() : device_id; | 238 GetDefaultOutputDeviceID() : device_id; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 266 | 258 |
| 267 // Tell the AudioManager to create a fake output device. | 259 // Tell the AudioManager to create a fake output device. |
| 268 output_params = AudioParameters( | 260 output_params = AudioParameters( |
| 269 AudioParameters::AUDIO_FAKE, params.channel_layout(), | 261 AudioParameters::AUDIO_FAKE, params.channel_layout(), |
| 270 params.sample_rate(), params.bits_per_sample(), | 262 params.sample_rate(), params.bits_per_sample(), |
| 271 params.frames_per_buffer()); | 263 params.frames_per_buffer()); |
| 272 } | 264 } |
| 273 } | 265 } |
| 274 | 266 |
| 275 DispatcherParams* dispatcher_params = | 267 DispatcherParams* dispatcher_params = |
| 276 new DispatcherParams(params, output_params, output_device_id, | 268 new DispatcherParams(params, output_params, output_device_id); |
| 277 input_device_id); | |
| 278 | 269 |
| 279 AudioOutputDispatchers::iterator it = | 270 AudioOutputDispatchers::iterator it = |
| 280 std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(), | 271 std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(), |
| 281 CompareByParams(dispatcher_params)); | 272 CompareByParams(dispatcher_params)); |
| 282 if (it != output_dispatchers_.end()) { | 273 if (it != output_dispatchers_.end()) { |
| 283 delete dispatcher_params; | 274 delete dispatcher_params; |
| 284 return new AudioOutputProxy((*it)->dispatcher.get()); | 275 return new AudioOutputProxy((*it)->dispatcher.get()); |
| 285 } | 276 } |
| 286 | 277 |
| 287 const base::TimeDelta kCloseDelay = | 278 const base::TimeDelta kCloseDelay = |
| 288 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds); | 279 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds); |
| 289 scoped_refptr<AudioOutputDispatcher> dispatcher; | 280 scoped_refptr<AudioOutputDispatcher> dispatcher; |
| 290 if (output_params.format() != AudioParameters::AUDIO_FAKE) { | 281 if (output_params.format() != AudioParameters::AUDIO_FAKE) { |
| 291 dispatcher = new AudioOutputResampler(this, params, output_params, | 282 dispatcher = new AudioOutputResampler(this, params, output_params, |
| 292 output_device_id, input_device_id, | 283 output_device_id, |
| 293 kCloseDelay); | 284 kCloseDelay); |
| 294 } else { | 285 } else { |
| 295 dispatcher = new AudioOutputDispatcherImpl(this, output_params, | 286 dispatcher = new AudioOutputDispatcherImpl(this, output_params, |
| 296 output_device_id, | 287 output_device_id, |
| 297 input_device_id, kCloseDelay); | 288 kCloseDelay); |
| 298 } | 289 } |
| 299 | 290 |
| 300 dispatcher_params->dispatcher = dispatcher; | 291 dispatcher_params->dispatcher = dispatcher; |
| 301 output_dispatchers_.push_back(dispatcher_params); | 292 output_dispatchers_.push_back(dispatcher_params); |
| 302 return new AudioOutputProxy(dispatcher.get()); | 293 return new AudioOutputProxy(dispatcher.get()); |
| 303 } | 294 } |
| 304 | 295 |
| 305 void AudioManagerBase::ShowAudioInputSettings() { | 296 void AudioManagerBase::ShowAudioInputSettings() { |
| 306 } | 297 } |
| 307 | 298 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 (*it)->dispatcher->CloseStreamsForWedgeFix(); | 436 (*it)->dispatcher->CloseStreamsForWedgeFix(); |
| 446 } | 437 } |
| 447 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); | 438 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); |
| 448 it != output_dispatchers_.end(); ++it) { | 439 it != output_dispatchers_.end(); ++it) { |
| 449 (*it)->dispatcher->RestartStreamsForWedgeFix(); | 440 (*it)->dispatcher->RestartStreamsForWedgeFix(); |
| 450 } | 441 } |
| 451 #endif | 442 #endif |
| 452 } | 443 } |
| 453 | 444 |
| 454 } // namespace media | 445 } // namespace media |
| OLD | NEW |