diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-23 22:34:24 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-23 22:34:24 +0000 |
commit | bbee17e594c08a4baf9379cdb22b4961a113434f (patch) | |
tree | 818c442ee3b3a4271e796e93d22880adee5315f4 /media/base/pipeline_impl_unittest.cc | |
parent | d691630d58df76b5dfc9d41c7b94d01738eb4c34 (diff) | |
download | chromium_src-bbee17e594c08a4baf9379cdb22b4961a113434f.zip chromium_src-bbee17e594c08a4baf9379cdb22b4961a113434f.tar.gz chromium_src-bbee17e594c08a4baf9379cdb22b4961a113434f.tar.bz2 |
Fix clock update behavior at the end of stream.
Sometimes the audio stream is slightly shorter than the video stream.
This can result in no audio data being written to the audio device if
you seek close to the end of the clip. This causes the pipeline to
hang because the video stream hasn't ended, but the clock hasn't been
started because no audio data is written to the device. This change
makes sure that the clock gets started if the audio stream has ended
and we are still waiting for a clock update.
I've also included a fix for a related problem where all of the audio
data gets written to the device, but clock updates don't occur on
playback_delay changes. This was contributing to the issue mentioned
above because up to a second worth of audio data can be covered by
the playback_delay. If this happens while seeking to within a second
of the clip end you won't get clock updates for the audio data.
BUG=52887
TEST=PipelineImplTest.AudioStreamShorterThanVideo
Review URL: http://codereview.chromium.org/5182008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67170 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/pipeline_impl_unittest.cc')
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index d61da09..f465e52 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -1,3 +1,4 @@ + // Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +7,7 @@ #include "base/callback.h" #include "base/stl_util-inl.h" +#include "media/base/clock_impl.h" #include "media/base/pipeline_impl.h" #include "media/base/media_format.h" #include "media/base/filters.h" @@ -632,8 +634,6 @@ TEST_F(PipelineImplTest, DisableAudioRenderer) { mocks_->audio_renderer()->SetPlaybackRate(1.0f); // Verify that ended event is fired when video ends. - EXPECT_CALL(*mocks_->audio_renderer(), HasEnded()) - .WillOnce(Return(false)); EXPECT_CALL(*mocks_->video_renderer(), HasEnded()) .WillOnce(Return(true)); EXPECT_CALL(callbacks_, OnEnded()); @@ -679,4 +679,78 @@ TEST_F(PipelineImplTest, EndedCallback) { host->NotifyEnded(); } +// Static function & time variable used to simulate changes in wallclock time. +static int64 g_static_clock_time; +static base::Time StaticClockFunction() { + return base::Time::FromInternalValue(g_static_clock_time); +} + +TEST_F(PipelineImplTest, AudioStreamShorterThanVideo) { + base::TimeDelta duration = base::TimeDelta::FromSeconds(10); + + CreateAudioStream(); + CreateVideoStream(); + MockDemuxerStreamVector streams; + streams.push_back(audio_stream()); + streams.push_back(video_stream()); + + InitializeDataSource(); + InitializeDemuxer(&streams, duration); + InitializeAudioDecoder(audio_stream()); + InitializeAudioRenderer(); + InitializeVideoDecoder(video_stream()); + InitializeVideoRenderer(); + InitializePipeline(); + + // For convenience to simulate filters calling the methods. + FilterHost* host = pipeline_; + + // Replace the clock so we can simulate wallclock time advancing w/o using + // Sleep. + pipeline_->clock_.reset(new ClockImpl(&StaticClockFunction)); + + EXPECT_EQ(0, host->GetTime().ToInternalValue()); + + float playback_rate = 1.0f; + EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate)); + pipeline_->SetPlaybackRate(playback_rate); + message_loop_.RunAllPending(); + + InSequence s; + + // Verify that the clock doesn't advance since it hasn't been started by + // a time update from the audio stream. + int64 start_time = host->GetTime().ToInternalValue(); + g_static_clock_time += + base::TimeDelta::FromMilliseconds(100).ToInternalValue(); + EXPECT_EQ(host->GetTime().ToInternalValue(), start_time); + + // Signal end of audio stream. + EXPECT_CALL(*mocks_->audio_renderer(), HasEnded()) + .WillOnce(Return(true)); + EXPECT_CALL(*mocks_->video_renderer(), HasEnded()) + .WillOnce(Return(false)); + host->NotifyEnded(); + message_loop_.RunAllPending(); + + // Verify that the clock advances. + start_time = host->GetTime().ToInternalValue(); + g_static_clock_time += + base::TimeDelta::FromMilliseconds(100).ToInternalValue(); + EXPECT_GT(host->GetTime().ToInternalValue(), start_time); + + // Signal end of video stream and make sure OnEnded() callback occurs. + EXPECT_CALL(*mocks_->audio_renderer(), HasEnded()) + .WillOnce(Return(true)); + EXPECT_CALL(*mocks_->video_renderer(), HasEnded()) + .WillOnce(Return(true)); + EXPECT_CALL(callbacks_, OnEnded()); + host->NotifyEnded(); +} + } // namespace media |