Index: media/base/android/media_codec_player_unittest.cc |
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc |
index f8b35f355e5c00febad0041912ac716d2660f020..afc7702f185f0bbf39e4d5f0287a3e632b4df343 100644 |
--- a/media/base/android/media_codec_player_unittest.cc |
+++ b/media/base/android/media_codec_player_unittest.cc |
@@ -237,7 +237,7 @@ class MockDemuxerAndroid : public DemuxerAndroid { |
// DemuxerAndroid implementation |
void Initialize(DemuxerAndroidClient* client) override; |
void RequestDemuxerData(DemuxerStream::Type type) override; |
- void RequestDemuxerSeek(const base::TimeDelta& time_to_seek, |
+ void RequestDemuxerSeek(const base::TimeDelta& seek_request, |
bool is_browser_seek) override; |
// Sets the audio data factory. |
@@ -250,6 +250,16 @@ class MockDemuxerAndroid : public DemuxerAndroid { |
video_factory_ = factory.Pass(); |
} |
+ // Set the preroll interval after seek for audio stream. |
+ void SetAudioPrerollInterval(base::TimeDelta value) { |
+ audio_preroll_interval_ = value; |
+ } |
+ |
+ // Set the preroll interval after seek for video stream. |
+ void SetVideoPrerollInterval(base::TimeDelta value) { |
+ video_preroll_interval_ = value; |
+ } |
+ |
// Sets the delay in OnDemuxerSeekDone response. |
void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; } |
@@ -270,6 +280,8 @@ class MockDemuxerAndroid : public DemuxerAndroid { |
scoped_ptr<DemuxerConfigs> pending_configs_; |
scoped_ptr<AudioFactory> audio_factory_; |
scoped_ptr<VideoFactory> video_factory_; |
+ base::TimeDelta audio_preroll_interval_; |
+ base::TimeDelta video_preroll_interval_; |
base::TimeDelta seek_done_delay_; |
int num_seeks_; |
int num_browser_seeks_; |
@@ -309,12 +321,17 @@ void MockDemuxerAndroid::RequestDemuxerData(DemuxerStream::Type type) { |
delay); |
} |
-void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& time_to_seek, |
+void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& seek_request, |
bool is_browser_seek) { |
// Tell data factories to start next chunk with the new timestamp. |
- if (audio_factory_) |
+ if (audio_factory_) { |
+ base::TimeDelta time_to_seek = |
+ std::max(base::TimeDelta(), seek_request - audio_preroll_interval_); |
audio_factory_->SeekTo(time_to_seek); |
+ } |
if (video_factory_) { |
+ base::TimeDelta time_to_seek = |
+ std::max(base::TimeDelta(), seek_request - video_preroll_interval_); |
video_factory_->SeekTo(time_to_seek); |
video_factory_->RequestKeyFrame(); |
} |
@@ -326,7 +343,7 @@ void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& time_to_seek, |
// Post OnDemuxerSeekDone() to the player. |
DCHECK(client_); |
base::TimeDelta reported_seek_time = |
- is_browser_seek ? time_to_seek : kNoTimestamp(); |
+ is_browser_seek ? seek_request : kNoTimestamp(); |
GetMediaTaskRunner()->PostDelayedTask( |
FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone, |
base::Unretained(client_), reported_seek_time), |
@@ -1055,4 +1072,55 @@ TEST_F(MediaCodecPlayerTest, VideoReleaseWhileWaitingForSeek) { |
&MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_)))); |
} |
+TEST_F(MediaCodecPlayerTest, VideoPrerollAfterSeek) { |
+ SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
+ |
+ // A simple test for preroll for video stream only. After the seek is done |
+ // the data factory generates the frames with pts before the seek time, and |
+ // they should not be rendered. We deduce which frame is rendered by looking |
+ // at the reported time progress. |
+ |
+ base::TimeDelta duration = base::TimeDelta::FromMilliseconds(600); |
+ base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500); |
+ base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
+ |
+ // Tell demuxer to make the first frame 100ms earlier than the seek request. |
+ demuxer_->SetVideoPrerollInterval(base::TimeDelta::FromMilliseconds(100)); |
+ |
+ demuxer_->SetVideoFactory( |
+ scoped_ptr<VideoFactory>(new VideoFactory(duration))); |
+ |
+ CreatePlayer(); |
+ SetVideoSurface(); |
+ |
+ // Wait till the player is initialized on media thread. |
+ EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized, |
+ base::Unretained(demuxer_)))); |
+ |
+ // Post configuration after the player has been initialized. |
+ demuxer_->PostInternalConfigs(); |
+ |
+ // Issue SeekTo(). |
+ player_->SeekTo(seek_position); |
+ |
+ // Start the playback and make sure it is started. |
+ player_->Start(); |
+ |
+ EXPECT_TRUE( |
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
+ base::Unretained(&manager_)), |
+ start_timeout)); |
+ |
+ // Wait for completion. |
+ EXPECT_TRUE( |
+ WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted, |
+ base::Unretained(&manager_)))); |
+ |
+ // The first pts should be equal than seek position even if video frames |
+ // started 100 ms eralier than the seek request. |
+ EXPECT_EQ(seek_position, manager_.pts_stat_.min()); |
+ |
+ EXPECT_EQ(6, manager_.pts_stat_.num_values()); |
+} |
+ |
} // namespace media |