From 4841a4bde07696cad73224a0c7e28ea9343c9e1c Mon Sep 17 00:00:00 2001 From: "davej@chromium.org" Date: Thu, 14 Apr 2011 23:34:00 +0000 Subject: Fix erratic HTML5 audio playback This was affecting all platforms. The major issue was that he SetPlaybackRate(1) which is used to start playback was being done in the middle of the series of Seek operations. So doing Seek() followed by SetPlaybackRate(1) was done, the Seek could immediately stop the playback. To fix, Seek() was made atomic with regards to SetPlaybackRate() by delaying the execution of SetPlaybackRate until after the Seek sequence has completely finished. To make things run even smoother, a short delay was added before recyclilng a used audio stream in the Dispatcher. This gives the stream time to 'power down' before being reused. Tested on Linux, Chrome-OS (Cr48) and Mac with great results, making HTML5 audio much more usable for games. BUG=73045,59369,59370,65618 TEST=Manual, Quickly playing/stopping HTML5 audio should play cleanly. Review URL: http://codereview.chromium.org/6822019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81670 0039d316-1c4b-4281-b951-d872f2087c98 --- media/base/pipeline_impl.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'media/base/pipeline_impl.cc') diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index f574b85..25bdf47 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -358,6 +358,7 @@ void PipelineImpl::ResetState() { seek_pending_ = false; tearing_down_ = false; error_caused_teardown_ = false; + playback_rate_change_pending_ = false; duration_ = kZero; buffered_time_ = kZero; buffered_bytes_ = 0; @@ -369,6 +370,7 @@ void PipelineImpl::ResetState() { volume_ = 1.0f; preload_ = AUTO; playback_rate_ = 0.0f; + pending_playback_rate_ = 0.0f; status_ = PIPELINE_OK; has_audio_ = false; has_video_ = false; @@ -780,6 +782,14 @@ void PipelineImpl::ErrorChangedTask(PipelineStatus error) { void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { DCHECK_EQ(MessageLoop::current(), message_loop_); + + // Suppress rate change until after seeking. + if (IsPipelineSeeking()) { + pending_playback_rate_ = playback_rate; + playback_rate_change_pending_ = true; + return; + } + { base::AutoLock auto_lock(lock_); clock_->SetPlaybackRate(playback_rate); @@ -959,6 +969,13 @@ void PipelineImpl::FilterStateTransitionTask() { seek_timestamp_ = base::TimeDelta(); seek_pending_ = false; + // If a playback rate change was requested during a seek, do it now that + // the seek has compelted. + if (playback_rate_change_pending_) { + playback_rate_change_pending_ = false; + PlaybackRateChangedTask(pending_playback_rate_); + } + base::AutoLock auto_lock(lock_); // We use audio stream to update the clock. So if there is such a stream, // we pause the clock until we receive a valid timestamp. -- cgit v1.1