diff options
author | enal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 00:45:22 +0000 |
---|---|---|
committer | enal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 00:45:22 +0000 |
commit | 6aa4a70d4ba67d84c2b00cf744371702f64d3a41 (patch) | |
tree | 6e24a882f5e69953807fb6749d90d8a25dc43c78 /media | |
parent | 619c5dba728763d3b6e1fbaa7537a4262810cb99 (diff) | |
download | chromium_src-6aa4a70d4ba67d84c2b00cf744371702f64d3a41.zip chromium_src-6aa4a70d4ba67d84c2b00cf744371702f64d3a41.tar.gz chromium_src-6aa4a70d4ba67d84c2b00cf744371702f64d3a41.tar.bz2 |
Workaround for OS/X crash when stop/starting stream too quickly.
We have much better fix in audio mixer, but we need some fix in M20.
On Mac do not allow starting of audio stream within 50ms of stopping.
BUG=128128
TEST=Crash should go away, or at least become much less frequent.
Review URL: https://chromiumcodereview.appspot.com/10387137
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137324 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/audio_output_controller.cc | 43 | ||||
-rw-r--r-- | media/audio/audio_output_controller.h | 3 |
2 files changed, 35 insertions, 11 deletions
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc index da90f10..13966d1 100644 --- a/media/audio/audio_output_controller.cc +++ b/media/audio/audio_output_controller.cc @@ -13,8 +13,13 @@ #include "base/time.h" using base::Time; +using base::TimeDelta; using base::WaitableEvent; +// Workaround for crbug.com/128128. +// Minimal delay between stream->Stop() and stream->Start(). +const int kMacWorkaroundInMilliseconds = 50; + namespace media { // Signal a pause in low-latency mode. @@ -33,7 +38,10 @@ AudioOutputController::AudioOutputController(EventHandler* handler, sync_reader_(sync_reader), message_loop_(NULL), number_polling_attempts_left_(0), - ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) { + ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)), + previous_stop_time_( + Time::Now() - + TimeDelta::FromMilliseconds(kMacWorkaroundInMilliseconds + 1)) { } AudioOutputController::~AudioOutputController() { @@ -170,7 +178,7 @@ void AudioOutputController::DoPlay() { FROM_HERE, base::Bind(&AudioOutputController::PollAndStartIfDataReady, weak_this_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); + TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); } void AudioOutputController::PollAndStartIfDataReady() { @@ -195,12 +203,25 @@ void AudioOutputController::PollAndStartIfDataReady() { FROM_HERE, base::Bind(&AudioOutputController::PollAndStartIfDataReady, weak_this_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); + TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); } } void AudioOutputController::StartStream() { DCHECK(message_loop_->BelongsToCurrentThread()); +#if defined(OS_MACOSX) + // HACK: workaround for crbug.com/128128. + // Mac OS crashes if we start playback too soon after previous ended. + // Audio mixer contains better fix, it keeps physical stream opened for + // some time after logical one is closed, so sequence of play / pause / play / + // pause / ... would reuse the same stream, but we need fix for M20. + // TODO(enal): Remove after turning on mixer by default. + while ((Time::Now() - previous_stop_time_).InMilliseconds() < + kMacWorkaroundInMilliseconds) { + base::PlatformThread::YieldCurrentThread(); + } +#endif + state_ = kPlaying; // We start the AudioOutputStream lazily. @@ -213,8 +234,13 @@ void AudioOutputController::StartStream() { void AudioOutputController::DoPause() { DCHECK(message_loop_->BelongsToCurrentThread()); - if (stream_) + if (stream_) { + // Then we stop the audio device. This is not the perfect solution + // because it discards all the internal buffer in the audio device. + // TODO(hclam): Actually pause the audio device. stream_->Stop(); + previous_stop_time_ = Time::Now(); + } switch (state_) { case kStarting: @@ -227,11 +253,6 @@ void AudioOutputController::DoPause() { case kPlaying: state_ = kPaused; - // Then we stop the audio device. This is not the perfect solution - // because it discards all the internal buffer in the audio device. - // TODO(hclam): Actually pause the audio device. - stream_->Stop(); - // Send a special pause mark to the low-latency audio thread. sync_reader_->UpdatePendingBytes(kPauseMark); @@ -306,11 +327,11 @@ void AudioOutputController::WaitTillDataReady() { if (!sync_reader_->DataReady()) { // In the different place we use different mechanism to poll, get max // polling delay from constants used there. - const base::TimeDelta kMaxPollingDelay = base::TimeDelta::FromMilliseconds( + const base::TimeDelta kMaxPollingDelay = TimeDelta::FromMilliseconds( kPollNumAttempts * kPollPauseInMilliseconds); Time start_time = Time::Now(); do { - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); + base::PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); } while (!sync_reader_->DataReady() && Time::Now() - start_time < kMaxPollingDelay); } diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h index 3c969ff..9e9945c 100644 --- a/media/audio/audio_output_controller.h +++ b/media/audio/audio_output_controller.h @@ -226,6 +226,9 @@ class MEDIA_EXPORT AudioOutputController // Also, if we're shutting down, we do not want to poll for more data. base::WeakPtrFactory<AudioOutputController> weak_this_; + // Workaround for Mac OS X bug, see crbug.com/128128. + base::Time previous_stop_time_; + DISALLOW_COPY_AND_ASSIGN(AudioOutputController); }; |