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/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/numerics/safe_conversions.h" | 11 #include "base/numerics/safe_conversions.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "base/trace_event/trace_event.h" |
14 #include "build/build_config.h" | 15 #include "build/build_config.h" |
15 #include "media/audio/audio_io.h" | 16 #include "media/audio/audio_io.h" |
16 #include "media/audio/audio_output_dispatcher_impl.h" | 17 #include "media/audio/audio_output_dispatcher_impl.h" |
17 #include "media/audio/audio_output_proxy.h" | 18 #include "media/audio/audio_output_proxy.h" |
18 #include "media/audio/sample_rates.h" | 19 #include "media/audio/sample_rates.h" |
19 #include "media/base/audio_converter.h" | 20 #include "media/base/audio_converter.h" |
20 #include "media/base/limits.h" | 21 #include "media/base/limits.h" |
21 | 22 |
22 namespace media { | 23 namespace media { |
23 | 24 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 } | 147 } |
147 | 148 |
148 AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, | 149 AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, |
149 const AudioParameters& input_params, | 150 const AudioParameters& input_params, |
150 const AudioParameters& output_params, | 151 const AudioParameters& output_params, |
151 const std::string& output_device_id, | 152 const std::string& output_device_id, |
152 const base::TimeDelta& close_delay) | 153 const base::TimeDelta& close_delay) |
153 : AudioOutputDispatcher(audio_manager, input_params, output_device_id), | 154 : AudioOutputDispatcher(audio_manager, input_params, output_device_id), |
154 close_delay_(close_delay), | 155 close_delay_(close_delay), |
155 output_params_(output_params), | 156 output_params_(output_params), |
156 streams_opened_(false) { | 157 original_output_params_(output_params), |
| 158 streams_opened_(false), |
| 159 reinitialize_timer_(FROM_HERE, |
| 160 close_delay_, |
| 161 base::Bind(&AudioOutputResampler::Reinitialize, |
| 162 base::Unretained(this)), |
| 163 false) { |
157 DCHECK(input_params.IsValid()); | 164 DCHECK(input_params.IsValid()); |
158 DCHECK(output_params.IsValid()); | 165 DCHECK(output_params.IsValid()); |
159 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); | 166 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); |
160 | 167 |
161 // Record UMA statistics for the hardware configuration. | 168 // Record UMA statistics for the hardware configuration. |
162 RecordStats(output_params); | 169 RecordStats(output_params); |
163 | 170 |
164 Initialize(); | 171 Initialize(); |
165 } | 172 } |
166 | 173 |
167 AudioOutputResampler::~AudioOutputResampler() { | 174 AudioOutputResampler::~AudioOutputResampler() { |
168 DCHECK(callbacks_.empty()); | 175 DCHECK(callbacks_.empty()); |
169 } | 176 } |
170 | 177 |
| 178 void AudioOutputResampler::Reinitialize() { |
| 179 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 180 DCHECK(streams_opened_); |
| 181 |
| 182 // We can only reinitialize the dispatcher if it has no active proxies. Check |
| 183 // if one has been created since the reinitialization timer was started. |
| 184 if (dispatcher_->HasOutputProxies()) |
| 185 return; |
| 186 |
| 187 // Log a trace event so we can get feedback in the field when this happens. |
| 188 TRACE_EVENT0("audio", "AudioOutputResampler::Reinitialize"); |
| 189 |
| 190 dispatcher_->Shutdown(); |
| 191 output_params_ = original_output_params_; |
| 192 streams_opened_ = false; |
| 193 Initialize(); |
| 194 } |
| 195 |
171 void AudioOutputResampler::Initialize() { | 196 void AudioOutputResampler::Initialize() { |
172 DCHECK(!streams_opened_); | 197 DCHECK(!streams_opened_); |
173 DCHECK(callbacks_.empty()); | 198 DCHECK(callbacks_.empty()); |
174 dispatcher_ = new AudioOutputDispatcherImpl( | 199 dispatcher_ = new AudioOutputDispatcherImpl( |
175 audio_manager_, output_params_, device_id_, close_delay_); | 200 audio_manager_, output_params_, device_id_, close_delay_); |
176 } | 201 } |
177 | 202 |
178 bool AudioOutputResampler::OpenStream() { | 203 bool AudioOutputResampler::OpenStream() { |
179 DCHECK(task_runner_->BelongsToCurrentThread()); | 204 DCHECK(task_runner_->BelongsToCurrentThread()); |
180 | 205 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 DCHECK(task_runner_->BelongsToCurrentThread()); | 300 DCHECK(task_runner_->BelongsToCurrentThread()); |
276 dispatcher_->CloseStream(stream_proxy); | 301 dispatcher_->CloseStream(stream_proxy); |
277 | 302 |
278 // We assume that StopStream() is always called prior to CloseStream(), so | 303 // We assume that StopStream() is always called prior to CloseStream(), so |
279 // that it is safe to delete the OnMoreDataConverter here. | 304 // that it is safe to delete the OnMoreDataConverter here. |
280 CallbackMap::iterator it = callbacks_.find(stream_proxy); | 305 CallbackMap::iterator it = callbacks_.find(stream_proxy); |
281 if (it != callbacks_.end()) { | 306 if (it != callbacks_.end()) { |
282 delete it->second; | 307 delete it->second; |
283 callbacks_.erase(it); | 308 callbacks_.erase(it); |
284 } | 309 } |
| 310 |
| 311 // Start the reinitialization timer if there are no active proxies and we're |
| 312 // not using the originally requested output parameters. This allows us to |
| 313 // recover from transient output creation errors. |
| 314 if (!dispatcher_->HasOutputProxies() && callbacks_.empty() && |
| 315 !output_params_.Equals(original_output_params_)) { |
| 316 reinitialize_timer_.Reset(); |
| 317 } |
285 } | 318 } |
286 | 319 |
287 void AudioOutputResampler::Shutdown() { | 320 void AudioOutputResampler::Shutdown() { |
288 DCHECK(task_runner_->BelongsToCurrentThread()); | 321 DCHECK(task_runner_->BelongsToCurrentThread()); |
289 | 322 |
290 // No AudioOutputProxy objects should hold a reference to us when we get | 323 // No AudioOutputProxy objects should hold a reference to us when we get |
291 // to this stage. | 324 // to this stage. |
292 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; | 325 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; |
293 | 326 |
294 dispatcher_->Shutdown(); | 327 dispatcher_->Shutdown(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 if (frames > 0 && frames < dest->frames()) | 386 if (frames > 0 && frames < dest->frames()) |
354 dest->ZeroFramesPartial(frames, dest->frames() - frames); | 387 dest->ZeroFramesPartial(frames, dest->frames() - frames); |
355 return frames > 0 ? 1 : 0; | 388 return frames > 0 ? 1 : 0; |
356 } | 389 } |
357 | 390 |
358 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { | 391 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { |
359 source_callback_->OnError(stream); | 392 source_callback_->OnError(stream); |
360 } | 393 } |
361 | 394 |
362 } // namespace media | 395 } // namespace media |
OLD | NEW |