Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Unified Diff: media/audio/audio_output_controller.cc

Issue 8371013: Harden audio output controller making it safe to call Pause() before (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/audio/audio_output_controller.cc
===================================================================
--- media/audio/audio_output_controller.cc (revision 106670)
+++ media/audio/audio_output_controller.cc (working copy)
@@ -176,9 +176,10 @@
// We can start from created or paused state.
if (state_ != kCreated && state_ != kPaused)
return;
- state_ = kPlaying;
if (LowLatencyMode()) {
+ state_ = kStarting;
+
// Ask for first packet.
sync_reader_->UpdatePendingBytes(0);
@@ -199,7 +200,7 @@
// Being paranoic: do nothing if we were stopped/paused
// after DoPlay() but before DoStartStream().
- if (state_ != kPlaying)
+ if (state_ != kStarting)
return;
if (--number_polling_attempts_left_ == 0 || sync_reader_->DataReady()) {
@@ -214,6 +215,7 @@
void AudioOutputController::StartStream() {
DCHECK_EQ(message_loop_, MessageLoop::current());
+ state_ = kPlaying;
// We start the AudioOutputStream lazily.
stream_->Start(this);
@@ -225,22 +227,38 @@
void AudioOutputController::DoPause() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // We can pause from started state.
- if (state_ != kPlaying)
- return;
- state_ = kPaused;
+ switch (state_) {
+ case kStarting:
+ // We were asked to pause while starting. There is delayed task that will
+ // try starting playback, and there is no way to remove that task from the
+ // queue. If we stop now that task will be executed anyway.
+ // We can set state to "paused" and avoid problem in the simple case,
+ // but we can be asked to start playback for 2nd time before it started
+ // for the 1st time, and there would be new set of problems.
+ // Simplest solution is to delay pause a little till playback starts.
+ message_loop_->PostDelayedTask(
acolwell GONE FROM CHROMIUM 2011/10/24 03:47:15 This doesn't smell right. Can we add a kPauseWhile
enal1 2011/10/24 16:28:29 Initially I wrote code similar to what you suggest
acolwell GONE FROM CHROMIUM 2011/10/24 16:59:58 I'm afraid I'm going to have to insist here. I REA
+ FROM_HERE,
+ base::Bind( &AudioOutputController::DoPause, this),
+ kPollPauseInMilliseconds);
+ break;
+ 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();
+ // 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();
- if (LowLatencyMode()) {
- // Send a special pause mark to the low-latency audio thread.
- sync_reader_->UpdatePendingBytes(kPauseMark);
+ if (LowLatencyMode()) {
+ // Send a special pause mark to the low-latency audio thread.
+ sync_reader_->UpdatePendingBytes(kPauseMark);
+ }
+
+ handler_->OnPaused(this);
+ break;
+ default:
+ return;
}
-
- handler_->OnPaused(this);
}
void AudioOutputController::DoFlush() {
@@ -287,10 +305,16 @@
// right away but when the stream is created we'll set the volume.
volume_ = volume;
- if (state_ != kPlaying && state_ != kPaused && state_ != kCreated)
- return;
-
- stream_->SetVolume(volume_);
+ switch (state_) {
+ case kCreated:
+ case kStarting:
+ case kPlaying:
+ case kPaused:
+ stream_->SetVolume(volume_);
+ break;
+ default:
+ return;
+ }
}
void AudioOutputController::DoReportError(int code) {

Powered by Google App Engine
This is Rietveld 408576698