summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_output_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/audio/audio_output_controller.cc')
-rw-r--r--media/audio/audio_output_controller.cc70
1 files changed, 48 insertions, 22 deletions
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 7118eaa..cd57bed 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -176,9 +176,10 @@ void AudioOutputController::DoPlay() {
// 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);
@@ -197,13 +198,20 @@ void AudioOutputController::DoPlay() {
void AudioOutputController::PollAndStartIfDataReady() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // Being paranoic: do nothing if we were stopped/paused
- // after DoPlay() but before DoStartStream().
- if (state_ != kPlaying)
+ // Being paranoic: do nothing if state unexpectedly changed.
+ if ((state_ != kStarting) && (state_ != kPausedWhenStarting))
return;
- if (--number_polling_attempts_left_ == 0 || sync_reader_->DataReady()) {
+ bool pausing = (state_ == kPausedWhenStarting);
+ // If we are ready to start the stream, start it.
+ // Of course we may have to stop it immediately...
+ if (--number_polling_attempts_left_ == 0 ||
+ pausing ||
+ sync_reader_->DataReady()) {
StartStream();
+ if (pausing) {
+ DoPause();
+ }
} else {
message_loop_->PostDelayedTask(
FROM_HERE,
@@ -214,6 +222,7 @@ void AudioOutputController::PollAndStartIfDataReady() {
void AudioOutputController::StartStream() {
DCHECK_EQ(message_loop_, MessageLoop::current());
+ state_ = kPlaying;
// We start the AudioOutputStream lazily.
stream_->Start(this);
@@ -225,22 +234,32 @@ void AudioOutputController::StartStream() {
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.
+ // Delay pausing, let delayed task to do pause after it start playback.
+ state_ = kPausedWhenStarting;
+ 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 +306,17 @@ void AudioOutputController::DoSetVolume(double volume) {
// 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 kPausedWhenStarting:
+ case kPlaying:
+ case kPaused:
+ stream_->SetVolume(volume_);
+ break;
+ default:
+ return;
+ }
}
void AudioOutputController::DoReportError(int code) {