summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authormiu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-03 12:19:55 +0000
committermiu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-03 12:19:55 +0000
commitc72d327cc55656ba65c6411137821fadd1ea3f2b (patch)
treef70148c9e5c5b9a50b7a306e57c971177e593d12 /media
parent96979827697cf7f6cab097b83787cbe1667e2e04 (diff)
downloadchromium_src-c72d327cc55656ba65c6411137821fadd1ea3f2b.zip
chromium_src-c72d327cc55656ba65c6411137821fadd1ea3f2b.tar.gz
chromium_src-c72d327cc55656ba65c6411137821fadd1ea3f2b.tar.bz2
Crash/stability fix for device change logic in AudioOutputController. The outstanding weak pointers need to be invalidated when streams are closed/re-created in order to auto-cancel the "polling starts."
Note: This is part one of a two-part patch. This encompasses changes which can only be applied to M24 and later. See http://codereview.chromium.org/11741010 for a more detailed description of the root cause and solution. BUG=167920 TEST=Ran media_unittests. TBR=dalecurtis@chromium.org Review URL: https://chromiumcodereview.appspot.com/11753008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174949 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/audio_output_controller.cc22
-rw-r--r--media/audio/audio_output_controller.h11
2 files changed, 15 insertions, 18 deletions
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 50850c9..a9dd2c8 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -119,7 +119,8 @@ void AudioOutputController::DoCreate() {
return;
DCHECK(state_ == kEmpty || state_ == kRecreating) << state_;
- DoStopCloseAndClearStream(NULL);
+ DoStopCloseAndClearStream(NULL); // Calls RemoveOutputDeviceChangeListener().
+
stream_ = audio_manager_->MakeAudioOutputStreamProxy(params_);
if (!stream_) {
state_ = kError;
@@ -140,8 +141,7 @@ void AudioOutputController::DoCreate() {
// Everything started okay, so register for state change callbacks if we have
// not already done so.
- if (state_ != kRecreating)
- audio_manager_->AddOutputDeviceChangeListener(this);
+ audio_manager_->AddOutputDeviceChangeListener(this);
// We have successfully opened the stream. Set the initial volume.
stream_->SetVolume(volume_);
@@ -177,6 +177,7 @@ void AudioOutputController::DoPlay() {
// TODO(vrk): The polling here and in WaitTillDataReady() is pretty clunky.
// Refine the API such that polling is no longer needed. (crbug.com/112196)
number_polling_attempts_left_ = kPollNumAttempts;
+ DCHECK(!weak_this_.HasWeakPtrs());
message_loop_->PostDelayedTask(
FROM_HERE,
base::Bind(&AudioOutputController::PollAndStartIfDataReady,
@@ -348,13 +349,12 @@ void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent* done) {
// Allow calling unconditionally and bail if we don't have a stream_ to close.
if (stream_) {
+ audio_manager_->RemoveOutputDeviceChangeListener(this);
+
stream_->Stop();
stream_->Close();
stream_ = NULL;
- audio_manager_->RemoveOutputDeviceChangeListener(this);
- audio_manager_ = NULL;
-
weak_this_.InvalidateWeakPtrs();
}
@@ -369,13 +369,9 @@ void AudioOutputController::OnDeviceChange() {
// We should always have a stream by this point.
CHECK(stream_);
- // Preserve the original state and shutdown the stream.
- State original_state = state_;
- stream_->Stop();
- stream_->Close();
- stream_ = NULL;
-
- // Recreate the stream, exit if we ran into an error.
+ // Recreate the stream (DoCreate() will first shut down an existing stream).
+ // Exit if we ran into an error.
+ const State original_state = state_;
state_ = kRecreating;
DoCreate();
if (!stream_ || state_ == kError)
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h
index 762a948..61718a3 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -196,10 +196,13 @@ class MEDIA_EXPORT AudioOutputController
// Signals event when done if it is not NULL.
void DoStopCloseAndClearStream(base::WaitableEvent *done);
- AudioManager* audio_manager_;
+ AudioManager* const audio_manager_;
// |handler_| may be called only if |state_| is not kClosed.
EventHandler* handler_;
+
+ // Note: It's important to invalidate the weak pointers whenever stream_ is
+ // changed. See comment for weak_this_.
AudioOutputStream* stream_;
// The current volume of the audio stream.
@@ -226,10 +229,8 @@ class MEDIA_EXPORT AudioOutputController
AudioParameters params_;
- // Used to post delayed tasks to ourselves that we can cancel.
- // We don't want the tasks to hold onto a reference as it will slow down
- // shutdown and force it to wait for the most delayed task.
- // Also, if we're shutting down, we do not want to poll for more data.
+ // Used to auto-cancel the delayed tasks that are created to poll for data
+ // (when starting-up a stream).
base::WeakPtrFactory<AudioOutputController> weak_this_;
DISALLOW_COPY_AND_ASSIGN(AudioOutputController);