summaryrefslogtreecommitdiffstats
path: root/media/base/pipeline_impl_unittest.cc
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-25 02:12:11 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-25 02:12:11 +0000
commit354589750cf3959506e5c2a34e66cc462fb7f3c4 (patch)
tree7d1a283d2cc5e4c3caf2686c42fcd5a0b5f8eb04 /media/base/pipeline_impl_unittest.cc
parent30bcf3718ace8f0ab46be60f318b476b658217b2 (diff)
downloadchromium_src-354589750cf3959506e5c2a34e66cc462fb7f3c4.zip
chromium_src-354589750cf3959506e5c2a34e66cc462fb7f3c4.tar.gz
chromium_src-354589750cf3959506e5c2a34e66cc462fb7f3c4.tar.bz2
Implemented proper pause-then-seek behaviour for the media pipeline.
MediaFilter now has asynchronous Play() and Pause() methods that are implemented by default. Since we are a completely pull-based system, it turns out only AudioRendererBase and VideoRendererBase need to override them to halt reading from decoders. When a seek is received by the pipeline, it goes through the following state transitions: 1) Playing -> Pausing -> Paused (notify filters to stop reading) 2) Paused -> Seeking (notify filters to flush buffers and preroll) 3) Seeking -> Playing (preroll completed, resume playback) The key to this system is that there must be no pending reads in *any* filter when we start transitioning into the seeking state. That means the audio/video renderers do not complete their pausing->paused transition until they have completed all pending reads. To reiterate, since we're pulled based if the renderers are not reading any data, then *nothing* is happening in the pipeline. We get a lot of nice benefits from this assertion, namely no callbacks are ever "lost", they are always replied to until we are fully paused. Furthermore, we can guarantee that the first buffer received after a Seek() will be guaranteed to be discontinuous. This change also properly handles end-of-stream, seeking from an end-of-stream state, and displaying frames while paused. In summary, I was able to call Seek() in a while(true) loop without crashing or going out of sync. BUG=16014,16021,17456 TEST=seeking should be way more robust Review URL: http://codereview.chromium.org/160005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21611 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/pipeline_impl_unittest.cc')
-rw-r--r--media/base/pipeline_impl_unittest.cc16
1 files changed, 16 insertions, 0 deletions
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index b2ebe54..e745761 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -68,6 +68,8 @@ class PipelineImplTest : public ::testing::Test {
EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull()))
.WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(0.0f));
+ EXPECT_CALL(*mocks_->data_source(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->data_source(), Stop());
}
@@ -80,6 +82,8 @@ class PipelineImplTest : public ::testing::Test {
EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams())
.WillRepeatedly(Return(streams->size()));
EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f));
+ EXPECT_CALL(*mocks_->demuxer(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->demuxer(), Stop());
// Configure the demuxer to return the streams.
@@ -95,6 +99,8 @@ class PipelineImplTest : public ::testing::Test {
EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream, NotNull()))
.WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(0.0f));
+ EXPECT_CALL(*mocks_->video_decoder(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->video_decoder(), Stop());
}
@@ -103,6 +109,8 @@ class PipelineImplTest : public ::testing::Test {
EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, NotNull()))
.WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(0.0f));
+ EXPECT_CALL(*mocks_->audio_decoder(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->audio_decoder(), Stop());
}
@@ -112,6 +120,8 @@ class PipelineImplTest : public ::testing::Test {
Initialize(mocks_->video_decoder(), NotNull()))
.WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f));
+ EXPECT_CALL(*mocks_->video_renderer(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->video_renderer(), Stop());
}
@@ -122,6 +132,8 @@ class PipelineImplTest : public ::testing::Test {
.WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f));
EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f));
+ EXPECT_CALL(*mocks_->audio_renderer(), Seek(base::TimeDelta(), NotNull()))
+ .WillOnce(Invoke(&RunFilterCallback));
EXPECT_CALL(*mocks_->audio_renderer(), Stop());
}
@@ -356,7 +368,11 @@ TEST_F(PipelineImplTest, Seek) {
pipeline_->Seek(expected,
NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_),
&CallbackHelper::OnSeek));
+
+ // We expect the time to be updated only after the seek has completed.
+ EXPECT_TRUE(expected != pipeline_->GetCurrentTime());
message_loop_.RunAllPending();
+ EXPECT_TRUE(expected == pipeline_->GetCurrentTime());
}
TEST_F(PipelineImplTest, SetVolume) {