Revert "Attempt to fix audio wedges by restarting all streams on OSX."

This reverts commit http://crrev.com/238501 in favor  a simpler approach
which delays stream creation around suspend and resume events:
http://crrev.com/247026

Care must be taken to monitor the UMA stat for increases after this lands.
I'll also communicate with the YT team on the bug/ to ensure they provide
some assistance in testing.

BUG=160920
TEST=No stream hangs.

Review URL: https://codereview.chromium.org/190553004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263076 0039d316-1c4b-4281-b951-d872f2087c98
parent d685c565
...@@ -176,11 +176,6 @@ class MEDIA_EXPORT AudioManager { ...@@ -176,11 +176,6 @@ class MEDIA_EXPORT AudioManager {
virtual scoped_ptr<AudioLog> CreateAudioLog( virtual scoped_ptr<AudioLog> CreateAudioLog(
AudioLogFactory::AudioComponent component) = 0; AudioLogFactory::AudioComponent component) = 0;
// Called when a component has detected a OS level audio wedge. Shuts down
// all active audio streams and then restarts them transparently. See
// http://crbug.com/160920
virtual void FixWedgedAudio() = 0;
protected: protected:
AudioManager(); AudioManager();
......
...@@ -400,32 +400,4 @@ scoped_ptr<AudioLog> AudioManagerBase::CreateAudioLog( ...@@ -400,32 +400,4 @@ scoped_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
return audio_log_factory_->CreateAudioLog(component); return audio_log_factory_->CreateAudioLog(component);
} }
void AudioManagerBase::FixWedgedAudio() {
DCHECK(task_runner_->BelongsToCurrentThread());
#if defined(OS_MACOSX)
// Through trial and error, we've found that one way to restore audio after a
// hang is to close all outstanding audio streams. Once all streams have been
// closed, new streams appear to work correctly.
//
// In Chrome terms, this means we need to ask all AudioOutputDispatchers to
// close all Open()'d streams. Once all streams across all dispatchers have
// been closed, we ask for all previously Start()'d streams to be recreated
// using the same AudioSourceCallback they had before.
//
// Since this operation takes place on the audio thread we can be sure that no
// other state-changing stream operations will take place while the fix is in
// progress.
//
// See http://crbug.com/160920 for additional details.
for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
it != output_dispatchers_.end(); ++it) {
(*it)->dispatcher->CloseStreamsForWedgeFix();
}
for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
it != output_dispatchers_.end(); ++it) {
(*it)->dispatcher->RestartStreamsForWedgeFix();
}
#endif
}
} // namespace media } // namespace media
...@@ -115,8 +115,6 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager { ...@@ -115,8 +115,6 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
virtual scoped_ptr<AudioLog> CreateAudioLog( virtual scoped_ptr<AudioLog> CreateAudioLog(
AudioLogFactory::AudioComponent component) OVERRIDE; AudioLogFactory::AudioComponent component) OVERRIDE;
virtual void FixWedgedAudio() OVERRIDE;
protected: protected:
AudioManagerBase(AudioLogFactory* audio_log_factory); AudioManagerBase(AudioLogFactory* audio_log_factory);
......
...@@ -435,15 +435,8 @@ void AudioOutputController::WedgeCheck() { ...@@ -435,15 +435,8 @@ void AudioOutputController::WedgeCheck() {
// If we should be playing and we haven't, that's a wedge. // If we should be playing and we haven't, that's a wedge.
if (state_ == kPlaying) { if (state_ == kPlaying) {
const bool playback_success = UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess",
base::AtomicRefCountIsOne(&on_more_io_data_called_); base::AtomicRefCountIsOne(&on_more_io_data_called_));
UMA_HISTOGRAM_BOOLEAN(
"Media.AudioOutputControllerPlaybackStartupSuccess", playback_success);
// Let the AudioManager try and fix it.
if (!playback_success)
audio_manager_->FixWedgedAudio();
} }
} }
......
...@@ -65,13 +65,6 @@ class MEDIA_EXPORT AudioOutputDispatcher ...@@ -65,13 +65,6 @@ class MEDIA_EXPORT AudioOutputDispatcher
// Called on the audio thread when the AudioManager is shutting down. // Called on the audio thread when the AudioManager is shutting down.
virtual void Shutdown() = 0; virtual void Shutdown() = 0;
// Called by the AudioManager to restart streams when a wedge is detected. A
// wedge means the OS failed to request any audio after StartStream(). When a
// wedge is detected all streams across all dispatchers must be closed. After
// all streams are closed, streams are restarted. See http://crbug.com/160920
virtual void CloseStreamsForWedgeFix() = 0;
virtual void RestartStreamsForWedgeFix() = 0;
const std::string& device_id() const { return device_id_; } const std::string& device_id() const { return device_id_; }
protected: protected:
......
...@@ -172,17 +172,4 @@ void AudioOutputDispatcherImpl::CloseIdleStreams(size_t keep_alive) { ...@@ -172,17 +172,4 @@ void AudioOutputDispatcherImpl::CloseIdleStreams(size_t keep_alive) {
idle_streams_.erase(idle_streams_.begin() + keep_alive, idle_streams_.end()); idle_streams_.erase(idle_streams_.begin() + keep_alive, idle_streams_.end());
} }
void AudioOutputDispatcherImpl::CloseStreamsForWedgeFix() {
DCHECK(task_runner_->BelongsToCurrentThread());
CloseAllIdleStreams();
}
void AudioOutputDispatcherImpl::RestartStreamsForWedgeFix() {
DCHECK(task_runner_->BelongsToCurrentThread());
// Should only be called when the dispatcher is used with fake streams which
// don't need to be shutdown or restarted.
CHECK_EQ(params_.format(), AudioParameters::AUDIO_FAKE);
}
} // namespace media } // namespace media
...@@ -61,9 +61,6 @@ class MEDIA_EXPORT AudioOutputDispatcherImpl : public AudioOutputDispatcher { ...@@ -61,9 +61,6 @@ class MEDIA_EXPORT AudioOutputDispatcherImpl : public AudioOutputDispatcher {
virtual void Shutdown() OVERRIDE; virtual void Shutdown() OVERRIDE;
virtual void CloseStreamsForWedgeFix() OVERRIDE;
virtual void RestartStreamsForWedgeFix() OVERRIDE;
private: private:
friend class base::RefCountedThreadSafe<AudioOutputDispatcherImpl>; friend class base::RefCountedThreadSafe<AudioOutputDispatcherImpl>;
virtual ~AudioOutputDispatcherImpl(); virtual ~AudioOutputDispatcherImpl();
......
...@@ -673,75 +673,4 @@ TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) { ...@@ -673,75 +673,4 @@ TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
EXPECT_TRUE(stream2.start_called()); EXPECT_TRUE(stream2.start_called());
} }
// Ensures the methods used to fix audio output wedges are working correctly.
TEST_F(AudioOutputResamplerTest, WedgeFix) {
MockAudioOutputStream stream1(&manager_, params_);
MockAudioOutputStream stream2(&manager_, params_);
MockAudioOutputStream stream3(&manager_, params_);
// Setup the mock such that all three streams are successfully created.
EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2))
.WillOnce(Return(&stream3));
// Stream1 should be able to successfully open and start.
EXPECT_CALL(stream1, Open())
.WillOnce(Return(true));
EXPECT_CALL(stream1, SetVolume(_));
EXPECT_CALL(stream2, Open())
.WillOnce(Return(true));
EXPECT_CALL(stream2, SetVolume(_));
// Open and start the first proxy and stream.
AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get());
EXPECT_TRUE(proxy1->Open());
proxy1->Start(&callback_);
OnStart();
// Open, but do not start the second proxy.
AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get());
EXPECT_TRUE(proxy2->Open());
// Open, start and then stop the third proxy.
AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get());
EXPECT_TRUE(proxy3->Open());
proxy3->Start(&callback_);
OnStart();
proxy3->Stop();
// Wait for stream to timeout and shutdown.
WaitForCloseTimer(&stream2);
EXPECT_CALL(stream1, Close());
resampler_->CloseStreamsForWedgeFix();
// Don't pump the MessageLoop between CloseStreamsForWedgeFix() and
// RestartStreamsForWedgeFix() to simulate intended usage. The OnStart() call
// will take care of necessary work.
// Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). No
// additional streams should be opened for proxy2 and proxy3.
EXPECT_CALL(stream3, Open())
.WillOnce(Return(true));
EXPECT_CALL(stream3, SetVolume(_));
resampler_->RestartStreamsForWedgeFix();
OnStart();
// Perform the required Stop()/Close() shutdown dance for each proxy.
proxy3->Close();
proxy2->Close();
proxy1->Stop();
CloseAndWaitForCloseTimer(proxy1, &stream3);
// Wait for all of the messages to fly and then verify stream behavior.
EXPECT_TRUE(stream1.stop_called());
EXPECT_TRUE(stream1.start_called());
EXPECT_TRUE(stream2.stop_called());
EXPECT_TRUE(stream2.start_called());
EXPECT_TRUE(stream3.stop_called());
EXPECT_TRUE(stream3.start_called());
}
} // namespace media } // namespace media
...@@ -298,37 +298,6 @@ void AudioOutputResampler::Shutdown() { ...@@ -298,37 +298,6 @@ void AudioOutputResampler::Shutdown() {
DCHECK(callbacks_.empty()); DCHECK(callbacks_.empty());
} }
void AudioOutputResampler::CloseStreamsForWedgeFix() {
DCHECK(task_runner_->BelongsToCurrentThread());
// Stop and close all active streams. Once all streams across all dispatchers
// have been closed the AudioManager will call RestartStreamsForWedgeFix().
for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
++it) {
if (it->second->started())
dispatcher_->StopStream(it->first);
dispatcher_->CloseStream(it->first);
}
// Close all idle streams as well.
dispatcher_->CloseStreamsForWedgeFix();
}
void AudioOutputResampler::RestartStreamsForWedgeFix() {
DCHECK(task_runner_->BelongsToCurrentThread());
// By opening all streams first and then starting them one by one we ensure
// the dispatcher only opens streams for those which will actually be used.
for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
++it) {
dispatcher_->OpenStream();
}
for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
++it) {
if (it->second->started())
dispatcher_->StartStream(it->second, it->first);
}
}
OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params,
const AudioParameters& output_params) const AudioParameters& output_params)
: io_ratio_(static_cast<double>(input_params.GetBytesPerSecond()) / : io_ratio_(static_cast<double>(input_params.GetBytesPerSecond()) /
......
...@@ -52,8 +52,6 @@ class MEDIA_EXPORT AudioOutputResampler : public AudioOutputDispatcher { ...@@ -52,8 +52,6 @@ class MEDIA_EXPORT AudioOutputResampler : public AudioOutputDispatcher {
double volume) OVERRIDE; double volume) OVERRIDE;
virtual void CloseStream(AudioOutputProxy* stream_proxy) OVERRIDE; virtual void CloseStream(AudioOutputProxy* stream_proxy) OVERRIDE;
virtual void Shutdown() OVERRIDE; virtual void Shutdown() OVERRIDE;
virtual void CloseStreamsForWedgeFix() OVERRIDE;
virtual void RestartStreamsForWedgeFix() OVERRIDE;
private: private:
friend class base::RefCountedThreadSafe<AudioOutputResampler>; friend class base::RefCountedThreadSafe<AudioOutputResampler>;
......
...@@ -107,6 +107,4 @@ scoped_ptr<AudioLog> MockAudioManager::CreateAudioLog( ...@@ -107,6 +107,4 @@ scoped_ptr<AudioLog> MockAudioManager::CreateAudioLog(
return scoped_ptr<AudioLog>(); return scoped_ptr<AudioLog>();
} }
void MockAudioManager::FixWedgedAudio() {}
} // namespace media. } // namespace media.
...@@ -70,8 +70,6 @@ class MockAudioManager : public media::AudioManager { ...@@ -70,8 +70,6 @@ class MockAudioManager : public media::AudioManager {
virtual scoped_ptr<AudioLog> CreateAudioLog( virtual scoped_ptr<AudioLog> CreateAudioLog(
AudioLogFactory::AudioComponent component) OVERRIDE; AudioLogFactory::AudioComponent component) OVERRIDE;
virtual void FixWedgedAudio() OVERRIDE;
protected: protected:
virtual ~MockAudioManager(); virtual ~MockAudioManager();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment