Index: media/audio/audio_output_resampler.cc |
diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc |
index 7aa32848f32971632628e988530d82b719f46548..f0534448d041c72fc8e3f2f5245c0d379be71b4e 100644 |
--- a/media/audio/audio_output_resampler.cc |
+++ b/media/audio/audio_output_resampler.cc |
@@ -11,6 +11,7 @@ |
#include "base/numerics/safe_conversions.h" |
#include "base/single_thread_task_runner.h" |
#include "base/time/time.h" |
+#include "base/trace_event/trace_event.h" |
#include "build/build_config.h" |
#include "media/audio/audio_io.h" |
#include "media/audio/audio_output_dispatcher_impl.h" |
@@ -153,7 +154,13 @@ AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, |
: AudioOutputDispatcher(audio_manager, input_params, output_device_id), |
close_delay_(close_delay), |
output_params_(output_params), |
- streams_opened_(false) { |
+ original_output_params_(output_params), |
+ streams_opened_(false), |
+ reinitialize_timer_(FROM_HERE, |
+ close_delay_, |
+ base::Bind(&AudioOutputResampler::Reinitialize, |
+ base::Unretained(this)), |
+ false) { |
DCHECK(input_params.IsValid()); |
DCHECK(output_params.IsValid()); |
DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); |
@@ -168,6 +175,24 @@ AudioOutputResampler::~AudioOutputResampler() { |
DCHECK(callbacks_.empty()); |
} |
+void AudioOutputResampler::Reinitialize() { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(streams_opened_); |
+ |
+ // We can only reinitialize the dispatcher if it has no active proxies. Check |
+ // if one has been created since the reinitialization timer was started. |
+ if (dispatcher_->HasOutputProxies()) |
+ return; |
+ |
+ // Log a trace event so we can get feedback in the field when this happens. |
+ TRACE_EVENT0("audio", "AudioOutputResampler::Reinitialize"); |
+ |
+ dispatcher_->Shutdown(); |
+ output_params_ = original_output_params_; |
+ streams_opened_ = false; |
+ Initialize(); |
+} |
+ |
void AudioOutputResampler::Initialize() { |
DCHECK(!streams_opened_); |
DCHECK(callbacks_.empty()); |
@@ -282,6 +307,14 @@ void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { |
delete it->second; |
callbacks_.erase(it); |
} |
+ |
+ // Start the reinitialization timer if there are no active proxies and we're |
+ // not using the originally requested output parameters. This allows us to |
+ // recover from transient output creation errors. |
+ if (!dispatcher_->HasOutputProxies() && callbacks_.empty() && |
+ !output_params_.Equals(original_output_params_)) { |
+ reinitialize_timer_.Reset(); |
+ } |
} |
void AudioOutputResampler::Shutdown() { |