| 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/command_line.h" | 8 #include "base/command_line.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" |
| 11 #include "media/audio/audio_output_dispatcher_impl.h" | 11 #include "media/audio/audio_output_dispatcher_impl.h" |
| 12 #include "media/audio/audio_output_proxy.h" | 12 #include "media/audio/audio_output_proxy.h" |
| 13 #include "media/audio/audio_output_resampler.h" | 13 #include "media/audio/audio_output_resampler.h" |
| 14 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
| 15 #include "media/audio/fake_audio_input_stream.h" | 15 #include "media/audio/fake_audio_input_stream.h" |
| 16 #include "media/audio/fake_audio_output_stream.h" | 16 #include "media/audio/fake_audio_output_stream.h" |
| 17 #include "media/audio/virtual_audio_input_stream.h" |
| 18 #include "media/audio/virtual_audio_output_stream.h" |
| 17 #include "media/base/media_switches.h" | 19 #include "media/base/media_switches.h" |
| 18 | 20 |
| 19 // TODO(dalecurtis): Temporarily disabled while switching pipeline to use float, | 21 // TODO(dalecurtis): Temporarily disabled while switching pipeline to use float, |
| 20 // http://crbug.com/114700 | 22 // http://crbug.com/114700 |
| 21 #if defined(ENABLE_AUDIO_MIXER) | 23 #if defined(ENABLE_AUDIO_MIXER) |
| 22 #include "media/audio/audio_output_mixer.h" | 24 #include "media/audio/audio_output_mixer.h" |
| 23 #endif | 25 #endif |
| 24 | 26 |
| 25 namespace media { | 27 namespace media { |
| 26 | 28 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 38 | 40 |
| 39 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; | 41 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
| 40 const char AudioManagerBase::kDefaultDeviceId[] = "default"; | 42 const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
| 41 | 43 |
| 42 AudioManagerBase::AudioManagerBase() | 44 AudioManagerBase::AudioManagerBase() |
| 43 : num_active_input_streams_(0), | 45 : num_active_input_streams_(0), |
| 44 max_num_output_streams_(kDefaultMaxOutputStreams), | 46 max_num_output_streams_(kDefaultMaxOutputStreams), |
| 45 max_num_input_streams_(kDefaultMaxInputStreams), | 47 max_num_input_streams_(kDefaultMaxInputStreams), |
| 46 num_output_streams_(0), | 48 num_output_streams_(0), |
| 47 num_input_streams_(0), | 49 num_input_streams_(0), |
| 48 audio_thread_(new base::Thread("AudioThread")) { | 50 audio_thread_(new base::Thread("AudioThread")), |
| 51 virtual_audio_input_stream_(NULL) { |
| 49 #if defined(OS_WIN) | 52 #if defined(OS_WIN) |
| 50 audio_thread_->init_com_with_mta(true); | 53 audio_thread_->init_com_with_mta(true); |
| 51 #endif | 54 #endif |
| 52 CHECK(audio_thread_->Start()); | 55 CHECK(audio_thread_->Start()); |
| 53 message_loop_ = audio_thread_->message_loop_proxy(); | 56 message_loop_ = audio_thread_->message_loop_proxy(); |
| 54 } | 57 } |
| 55 | 58 |
| 56 AudioManagerBase::~AudioManagerBase() { | 59 AudioManagerBase::~AudioManagerBase() { |
| 57 // The platform specific AudioManager implementation must have already | 60 // The platform specific AudioManager implementation must have already |
| 58 // stopped the audio thread. Otherwise, we may destroy audio streams before | 61 // stopped the audio thread. Otherwise, we may destroy audio streams before |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 return NULL; | 96 return NULL; |
| 94 } | 97 } |
| 95 | 98 |
| 96 // If there are no audio output devices we should use a FakeAudioOutputStream | 99 // If there are no audio output devices we should use a FakeAudioOutputStream |
| 97 // to ensure video playback continues to work. | 100 // to ensure video playback continues to work. |
| 98 bool audio_output_disabled = | 101 bool audio_output_disabled = |
| 99 params.format() == AudioParameters::AUDIO_FAKE || | 102 params.format() == AudioParameters::AUDIO_FAKE || |
| 100 !HasAudioOutputDevices(); | 103 !HasAudioOutputDevices(); |
| 101 | 104 |
| 102 AudioOutputStream* stream = NULL; | 105 AudioOutputStream* stream = NULL; |
| 103 if (audio_output_disabled) { | 106 if (virtual_audio_input_stream_) { |
| 107 #if defined(OS_IOS) |
| 108 // We do not currently support iOS. It does not link. |
| 109 NOTIMPLEMENTED(); |
| 110 return NULL; |
| 111 #else |
| 112 stream = VirtualAudioOutputStream::MakeStream(this, params, message_loop_, |
| 113 virtual_audio_input_stream_); |
| 114 #endif |
| 115 } else if (audio_output_disabled) { |
| 104 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 116 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
| 105 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { | 117 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { |
| 106 stream = MakeLinearOutputStream(params); | 118 stream = MakeLinearOutputStream(params); |
| 107 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 119 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
| 108 stream = MakeLowLatencyOutputStream(params); | 120 stream = MakeLowLatencyOutputStream(params); |
| 109 } | 121 } |
| 110 | 122 |
| 111 if (stream) | 123 if (stream) |
| 112 ++num_output_streams_; | 124 ++num_output_streams_; |
| 113 | 125 |
| 114 return stream; | 126 return stream; |
| 115 } | 127 } |
| 116 | 128 |
| 117 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 129 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
| 118 const AudioParameters& params, const std::string& device_id) { | 130 const AudioParameters& params, const std::string& device_id) { |
| 119 if (!params.IsValid() || (params.channels() > kMaxInputChannels) || | 131 if (!params.IsValid() || (params.channels() > kMaxInputChannels) || |
| 120 device_id.empty()) { | 132 device_id.empty()) { |
| 121 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; | 133 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; |
| 122 return NULL; | 134 return NULL; |
| 123 } | 135 } |
| 124 | 136 |
| 125 if (num_input_streams_ >= max_num_input_streams_) { | 137 if (num_input_streams_ >= max_num_input_streams_) { |
| 126 DLOG(ERROR) << "Number of opened input audio streams " | 138 DLOG(ERROR) << "Number of opened input audio streams " |
| 127 << num_input_streams_ | 139 << num_input_streams_ |
| 128 << " exceed the max allowed number " << max_num_input_streams_; | 140 << " exceed the max allowed number " << max_num_input_streams_; |
| 129 return NULL; | 141 return NULL; |
| 130 } | 142 } |
| 131 | 143 |
| 132 AudioInputStream* stream = NULL; | 144 AudioInputStream* stream = NULL; |
| 133 if (params.format() == AudioParameters::AUDIO_FAKE) { | 145 if (params.format() == AudioParameters::AUDIO_VIRTUAL) { |
| 146 #if defined(OS_IOS) |
| 147 // We do not currently support iOS. |
| 148 NOTIMPLEMENTED(); |
| 149 return NULL; |
| 150 #else |
| 151 // TODO(justinlin): Currently, audio mirroring will only work for the first |
| 152 // request. Subsequent requests will not get audio. |
| 153 if (!virtual_audio_input_stream_) { |
| 154 virtual_audio_input_stream_ = |
| 155 VirtualAudioInputStream::MakeStream(this, params, message_loop_); |
| 156 stream = virtual_audio_input_stream_; |
| 157 DVLOG(1) << "Virtual audio input stream created."; |
| 158 |
| 159 // Make all current output streams recreate themselves as |
| 160 // VirtualAudioOutputStreams that will attach to the above |
| 161 // VirtualAudioInputStream. |
| 162 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 163 &AudioManagerBase::NotifyAllOutputDeviceChangeListeners, |
| 164 base::Unretained(this))); |
| 165 } else { |
| 166 stream = NULL; |
| 167 } |
| 168 #endif |
| 169 } else if (params.format() == AudioParameters::AUDIO_FAKE) { |
| 134 stream = FakeAudioInputStream::MakeFakeStream(this, params); | 170 stream = FakeAudioInputStream::MakeFakeStream(this, params); |
| 135 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { | 171 } else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) { |
| 136 stream = MakeLinearInputStream(params, device_id); | 172 stream = MakeLinearInputStream(params, device_id); |
| 137 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 173 } else if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
| 138 stream = MakeLowLatencyInputStream(params, device_id); | 174 stream = MakeLowLatencyInputStream(params, device_id); |
| 139 } | 175 } |
| 140 | 176 |
| 141 if (stream) | 177 if (stream) |
| 142 ++num_input_streams_; | 178 ++num_input_streams_; |
| 143 | 179 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 273 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. |
| 238 // For example, pass the ownership to AudioManager so it can delete the | 274 // For example, pass the ownership to AudioManager so it can delete the |
| 239 // streams. | 275 // streams. |
| 240 num_output_streams_--; | 276 num_output_streams_--; |
| 241 delete stream; | 277 delete stream; |
| 242 } | 278 } |
| 243 | 279 |
| 244 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 280 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
| 245 DCHECK(stream); | 281 DCHECK(stream); |
| 246 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 282 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. |
| 283 |
| 284 if (virtual_audio_input_stream_ == stream) { |
| 285 DVLOG(1) << "Virtual audio input stream stopping."; |
| 286 virtual_audio_input_stream_->Stop(); |
| 287 virtual_audio_input_stream_ = NULL; |
| 288 |
| 289 // Make all VirtualAudioOutputStreams unregister from the |
| 290 // VirtualAudioInputStream and recreate themselves as regular audio streams |
| 291 // to return sound to hardware. |
| 292 NotifyAllOutputDeviceChangeListeners(); |
| 293 } |
| 294 |
| 247 num_input_streams_--; | 295 num_input_streams_--; |
| 248 delete stream; | 296 delete stream; |
| 249 } | 297 } |
| 250 | 298 |
| 251 void AudioManagerBase::IncreaseActiveInputStreamCount() { | 299 void AudioManagerBase::IncreaseActiveInputStreamCount() { |
| 252 base::AtomicRefCountInc(&num_active_input_streams_); | 300 base::AtomicRefCountInc(&num_active_input_streams_); |
| 253 } | 301 } |
| 254 | 302 |
| 255 void AudioManagerBase::DecreaseActiveInputStreamCount() { | 303 void AudioManagerBase::DecreaseActiveInputStreamCount() { |
| 256 DCHECK(IsRecordingInProcess()); | 304 DCHECK(IsRecordingInProcess()); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 output_listeners_.RemoveObserver(listener); | 388 output_listeners_.RemoveObserver(listener); |
| 341 } | 389 } |
| 342 | 390 |
| 343 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { | 391 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { |
| 344 DCHECK(message_loop_->BelongsToCurrentThread()); | 392 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 345 DVLOG(1) << "Firing OnDeviceChange() notifications."; | 393 DVLOG(1) << "Firing OnDeviceChange() notifications."; |
| 346 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); | 394 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); |
| 347 } | 395 } |
| 348 | 396 |
| 349 } // namespace media | 397 } // namespace media |
| OLD | NEW |