| 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_output_resampler.h" | 5 #include "media/audio/audio_output_resampler.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/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/message_loop/message_loop.h" | |
| 11 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/single_thread_task_runner.h" |
| 12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "media/audio/audio_io.h" | 14 #include "media/audio/audio_io.h" |
| 15 #include "media/audio/audio_output_dispatcher_impl.h" | 15 #include "media/audio/audio_output_dispatcher_impl.h" |
| 16 #include "media/audio/audio_output_proxy.h" | 16 #include "media/audio/audio_output_proxy.h" |
| 17 #include "media/audio/sample_rates.h" | 17 #include "media/audio/sample_rates.h" |
| 18 #include "media/base/audio_converter.h" | 18 #include "media/base/audio_converter.h" |
| 19 #include "media/base/limits.h" | 19 #include "media/base/limits.h" |
| 20 | 20 |
| 21 namespace media { | 21 namespace media { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 | 168 |
| 169 void AudioOutputResampler::Initialize() { | 169 void AudioOutputResampler::Initialize() { |
| 170 DCHECK(!streams_opened_); | 170 DCHECK(!streams_opened_); |
| 171 DCHECK(callbacks_.empty()); | 171 DCHECK(callbacks_.empty()); |
| 172 dispatcher_ = new AudioOutputDispatcherImpl( | 172 dispatcher_ = new AudioOutputDispatcherImpl( |
| 173 audio_manager_, output_params_, output_device_id_, input_device_id_, | 173 audio_manager_, output_params_, output_device_id_, input_device_id_, |
| 174 close_delay_); | 174 close_delay_); |
| 175 } | 175 } |
| 176 | 176 |
| 177 bool AudioOutputResampler::OpenStream() { | 177 bool AudioOutputResampler::OpenStream() { |
| 178 DCHECK(message_loop_->BelongsToCurrentThread()); | 178 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 179 | 179 |
| 180 if (dispatcher_->OpenStream()) { | 180 if (dispatcher_->OpenStream()) { |
| 181 // Only record the UMA statistic if we didn't fallback during construction | 181 // Only record the UMA statistic if we didn't fallback during construction |
| 182 // and only for the first stream we open. | 182 // and only for the first stream we open. |
| 183 if (!streams_opened_ && | 183 if (!streams_opened_ && |
| 184 output_params_.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 184 output_params_.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
| 185 UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", false); | 185 UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", false); |
| 186 } | 186 } |
| 187 streams_opened_ = true; | 187 streams_opened_ = true; |
| 188 return true; | 188 return true; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 streams_opened_ = true; | 228 streams_opened_ = true; |
| 229 return true; | 229 return true; |
| 230 } | 230 } |
| 231 | 231 |
| 232 return false; | 232 return false; |
| 233 } | 233 } |
| 234 | 234 |
| 235 bool AudioOutputResampler::StartStream( | 235 bool AudioOutputResampler::StartStream( |
| 236 AudioOutputStream::AudioSourceCallback* callback, | 236 AudioOutputStream::AudioSourceCallback* callback, |
| 237 AudioOutputProxy* stream_proxy) { | 237 AudioOutputProxy* stream_proxy) { |
| 238 DCHECK(message_loop_->BelongsToCurrentThread()); | 238 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 239 | 239 |
| 240 OnMoreDataConverter* resampler_callback = NULL; | 240 OnMoreDataConverter* resampler_callback = NULL; |
| 241 CallbackMap::iterator it = callbacks_.find(stream_proxy); | 241 CallbackMap::iterator it = callbacks_.find(stream_proxy); |
| 242 if (it == callbacks_.end()) { | 242 if (it == callbacks_.end()) { |
| 243 resampler_callback = new OnMoreDataConverter(params_, output_params_); | 243 resampler_callback = new OnMoreDataConverter(params_, output_params_); |
| 244 callbacks_[stream_proxy] = resampler_callback; | 244 callbacks_[stream_proxy] = resampler_callback; |
| 245 } else { | 245 } else { |
| 246 resampler_callback = it->second; | 246 resampler_callback = it->second; |
| 247 } | 247 } |
| 248 | 248 |
| 249 resampler_callback->Start(callback); | 249 resampler_callback->Start(callback); |
| 250 bool result = dispatcher_->StartStream(resampler_callback, stream_proxy); | 250 bool result = dispatcher_->StartStream(resampler_callback, stream_proxy); |
| 251 if (!result) | 251 if (!result) |
| 252 resampler_callback->Stop(); | 252 resampler_callback->Stop(); |
| 253 return result; | 253 return result; |
| 254 } | 254 } |
| 255 | 255 |
| 256 void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy, | 256 void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy, |
| 257 double volume) { | 257 double volume) { |
| 258 DCHECK(message_loop_->BelongsToCurrentThread()); | 258 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 259 dispatcher_->StreamVolumeSet(stream_proxy, volume); | 259 dispatcher_->StreamVolumeSet(stream_proxy, volume); |
| 260 } | 260 } |
| 261 | 261 |
| 262 void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) { | 262 void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) { |
| 263 DCHECK(message_loop_->BelongsToCurrentThread()); | 263 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 264 dispatcher_->StopStream(stream_proxy); | 264 dispatcher_->StopStream(stream_proxy); |
| 265 | 265 |
| 266 // Now that StopStream() has completed the underlying physical stream should | 266 // Now that StopStream() has completed the underlying physical stream should |
| 267 // be stopped and no longer calling OnMoreData(), making it safe to Stop() the | 267 // be stopped and no longer calling OnMoreData(), making it safe to Stop() the |
| 268 // OnMoreDataConverter. | 268 // OnMoreDataConverter. |
| 269 CallbackMap::iterator it = callbacks_.find(stream_proxy); | 269 CallbackMap::iterator it = callbacks_.find(stream_proxy); |
| 270 if (it != callbacks_.end()) | 270 if (it != callbacks_.end()) |
| 271 it->second->Stop(); | 271 it->second->Stop(); |
| 272 } | 272 } |
| 273 | 273 |
| 274 void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { | 274 void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { |
| 275 DCHECK(message_loop_->BelongsToCurrentThread()); | 275 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 276 dispatcher_->CloseStream(stream_proxy); | 276 dispatcher_->CloseStream(stream_proxy); |
| 277 | 277 |
| 278 // We assume that StopStream() is always called prior to CloseStream(), so | 278 // We assume that StopStream() is always called prior to CloseStream(), so |
| 279 // that it is safe to delete the OnMoreDataConverter here. | 279 // that it is safe to delete the OnMoreDataConverter here. |
| 280 CallbackMap::iterator it = callbacks_.find(stream_proxy); | 280 CallbackMap::iterator it = callbacks_.find(stream_proxy); |
| 281 if (it != callbacks_.end()) { | 281 if (it != callbacks_.end()) { |
| 282 delete it->second; | 282 delete it->second; |
| 283 callbacks_.erase(it); | 283 callbacks_.erase(it); |
| 284 } | 284 } |
| 285 } | 285 } |
| 286 | 286 |
| 287 void AudioOutputResampler::Shutdown() { | 287 void AudioOutputResampler::Shutdown() { |
| 288 DCHECK(message_loop_->BelongsToCurrentThread()); | 288 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 289 | 289 |
| 290 // No AudioOutputProxy objects should hold a reference to us when we get | 290 // No AudioOutputProxy objects should hold a reference to us when we get |
| 291 // to this stage. | 291 // to this stage. |
| 292 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; | 292 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; |
| 293 | 293 |
| 294 dispatcher_->Shutdown(); | 294 dispatcher_->Shutdown(); |
| 295 DCHECK(callbacks_.empty()); | 295 DCHECK(callbacks_.empty()); |
| 296 } | 296 } |
| 297 | 297 |
| 298 OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, | 298 OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 return frames > 0 ? 1 : 0; | 385 return frames > 0 ? 1 : 0; |
| 386 } | 386 } |
| 387 | 387 |
| 388 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { | 388 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { |
| 389 base::AutoLock auto_lock(source_lock_); | 389 base::AutoLock auto_lock(source_lock_); |
| 390 if (source_callback_) | 390 if (source_callback_) |
| 391 source_callback_->OnError(stream); | 391 source_callback_->OnError(stream); |
| 392 } | 392 } |
| 393 | 393 |
| 394 } // namespace media | 394 } // namespace media |
| OLD | NEW |