| 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 f818bac89b74ab4a650725ec41e6f0d889372bed..f8b35f355e5c00febad0041912ac716d2660f020 100644
|
| --- a/media/base/android/media_codec_player_unittest.cc
|
| +++ b/media/base/android/media_codec_player_unittest.cc
|
| @@ -58,7 +58,9 @@ bool AlmostEqual(base::TimeDelta a, base::TimeDelta b, double tolerance_ms) {
|
| class MockMediaPlayerManager : public MediaPlayerManager {
|
| public:
|
| MockMediaPlayerManager()
|
| - : playback_completed_(false), weak_ptr_factory_(this) {}
|
| + : playback_completed_(false),
|
| + num_seeks_completed_(0),
|
| + weak_ptr_factory_(this) {}
|
| ~MockMediaPlayerManager() override {}
|
|
|
| MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; }
|
| @@ -88,7 +90,9 @@ class MockMediaPlayerManager : public MediaPlayerManager {
|
| void OnMediaInterrupted(int player_id) override {}
|
| void OnBufferingUpdate(int player_id, int percentage) override {}
|
| void OnSeekComplete(int player_id,
|
| - const base::TimeDelta& current_time) override {}
|
| + const base::TimeDelta& current_time) override {
|
| + ++num_seeks_completed_;
|
| + }
|
| void OnError(int player_id, int error) override {}
|
| void OnVideoSizeChanged(int player_id, int width, int height) override {}
|
| void OnAudibleStateChanged(int player_id, bool is_audible_now) override {}
|
| @@ -110,6 +114,7 @@ class MockMediaPlayerManager : public MediaPlayerManager {
|
| bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const {
|
| return pts_stat_.max() > pts;
|
| }
|
| + bool IsSeekCompleted() const { return num_seeks_completed_ > 0; }
|
|
|
| struct MediaMetadata {
|
| base::TimeDelta duration;
|
| @@ -124,6 +129,7 @@ class MockMediaPlayerManager : public MediaPlayerManager {
|
|
|
| private:
|
| bool playback_completed_;
|
| + int num_seeks_completed_;
|
|
|
| base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_;
|
|
|
| @@ -175,13 +181,16 @@ class AudioFactory : public TestDataFactory {
|
| class VideoFactory : public TestDataFactory {
|
| public:
|
| VideoFactory(base::TimeDelta duration)
|
| - : TestDataFactory("h264-320x180-frame-%d", duration, kVideoFramePeriod) {}
|
| + : TestDataFactory("h264-320x180-frame-%d", duration, kVideoFramePeriod),
|
| + key_frame_requested_(true) {}
|
|
|
| DemuxerConfigs GetConfigs() const override {
|
| return TestDataFactory::CreateVideoConfigs(kCodecH264, duration_,
|
| gfx::Size(320, 180));
|
| }
|
|
|
| + void RequestKeyFrame() { key_frame_requested_ = true; }
|
| +
|
| protected:
|
| void ModifyAccessUnit(int index_in_chunk, AccessUnit* unit) override {
|
| // The frames are taken from High profile and some are B-frames.
|
| @@ -196,7 +205,8 @@ class VideoFactory : public TestDataFactory {
|
| // Swap pts for second and third frames. Make first frame a key frame.
|
| switch (index_in_chunk) {
|
| case 0: // first frame
|
| - unit->is_key_frame = true;
|
| + unit->is_key_frame = key_frame_requested_;
|
| + key_frame_requested_ = false;
|
| break;
|
| case 1: // second frame
|
| unit->timestamp += frame_period_;
|
| @@ -211,13 +221,17 @@ class VideoFactory : public TestDataFactory {
|
| break;
|
| }
|
| }
|
| +
|
| + private:
|
| + bool key_frame_requested_;
|
| };
|
|
|
| // Mock of DemuxerAndroid for testing purpose.
|
|
|
| class MockDemuxerAndroid : public DemuxerAndroid {
|
| public:
|
| - MockDemuxerAndroid() : client_(nullptr) {}
|
| + MockDemuxerAndroid()
|
| + : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {}
|
| ~MockDemuxerAndroid() override {}
|
|
|
| // DemuxerAndroid implementation
|
| @@ -227,15 +241,18 @@ class MockDemuxerAndroid : public DemuxerAndroid {
|
| bool is_browser_seek) override;
|
|
|
| // Sets the audio data factory.
|
| - void SetAudioFactory(scoped_ptr<TestDataFactory> factory) {
|
| + void SetAudioFactory(scoped_ptr<AudioFactory> factory) {
|
| audio_factory_ = factory.Pass();
|
| }
|
|
|
| // Sets the video data factory.
|
| - void SetVideoFactory(scoped_ptr<TestDataFactory> factory) {
|
| + void SetVideoFactory(scoped_ptr<VideoFactory> factory) {
|
| video_factory_ = factory.Pass();
|
| }
|
|
|
| + // Sets the delay in OnDemuxerSeekDone response.
|
| + void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; }
|
| +
|
| // Post DemuxerConfigs to the client (i.e. the player) on correct thread.
|
| void PostConfigs(const DemuxerConfigs& configs);
|
|
|
| @@ -245,12 +262,17 @@ class MockDemuxerAndroid : public DemuxerAndroid {
|
| // Conditions to wait for.
|
| bool IsInitialized() const { return client_; }
|
| bool HasPendingConfigs() const { return pending_configs_; }
|
| + bool ReceivedSeekRequest() const { return num_seeks_ > 0; }
|
| + bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; }
|
|
|
| private:
|
| DemuxerAndroidClient* client_;
|
| scoped_ptr<DemuxerConfigs> pending_configs_;
|
| - scoped_ptr<TestDataFactory> audio_factory_;
|
| - scoped_ptr<TestDataFactory> video_factory_;
|
| + scoped_ptr<AudioFactory> audio_factory_;
|
| + scoped_ptr<VideoFactory> video_factory_;
|
| + base::TimeDelta seek_done_delay_;
|
| + int num_seeks_;
|
| + int num_browser_seeks_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid);
|
| };
|
| @@ -292,16 +314,23 @@ void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& time_to_seek,
|
| // Tell data factories to start next chunk with the new timestamp.
|
| if (audio_factory_)
|
| audio_factory_->SeekTo(time_to_seek);
|
| - if (video_factory_)
|
| + if (video_factory_) {
|
| video_factory_->SeekTo(time_to_seek);
|
| + video_factory_->RequestKeyFrame();
|
| + }
|
| +
|
| + ++num_seeks_;
|
| + if (is_browser_seek)
|
| + ++num_browser_seeks_;
|
|
|
| // Post OnDemuxerSeekDone() to the player.
|
| DCHECK(client_);
|
| base::TimeDelta reported_seek_time =
|
| is_browser_seek ? time_to_seek : kNoTimestamp();
|
| - GetMediaTaskRunner()->PostTask(
|
| + GetMediaTaskRunner()->PostDelayedTask(
|
| FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone,
|
| - base::Unretained(client_), reported_seek_time));
|
| + base::Unretained(client_), reported_seek_time),
|
| + seek_done_delay_);
|
| }
|
|
|
| void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) {
|
| @@ -347,6 +376,8 @@ class MediaCodecPlayerTest : public testing::Test {
|
|
|
| void CreatePlayer();
|
| void SetVideoSurface();
|
| + void SetVideoSurfaceB();
|
| + void RemoveVideoSurface();
|
|
|
| // Waits for condition to become true or for timeout to expire.
|
| // Returns true if the condition becomes true.
|
| @@ -363,10 +394,15 @@ class MediaCodecPlayerTest : public testing::Test {
|
| const base::TimeDelta& pts,
|
| const base::TimeDelta& timeout = kDefaultTimeout);
|
|
|
| + // Helper method that starts video only stream. Waits till it actually
|
| + // started.
|
| + void StartVideoPlayback(base::TimeDelta duration);
|
| +
|
| base::MessageLoop message_loop_;
|
| MockMediaPlayerManager manager_;
|
| MockDemuxerAndroid* demuxer_; // owned by player_
|
| - scoped_refptr<gfx::SurfaceTexture> surface_texture_;
|
| + scoped_refptr<gfx::SurfaceTexture> surface_texture_a_;
|
| + scoped_refptr<gfx::SurfaceTexture> surface_texture_b_;
|
| MediaCodecPlayer* player_; // raw pointer due to DeleteOnCorrectThread()
|
|
|
| private:
|
| @@ -400,13 +436,26 @@ void MediaCodecPlayerTest::CreatePlayer() {
|
| }
|
|
|
| void MediaCodecPlayerTest::SetVideoSurface() {
|
| - surface_texture_ = gfx::SurfaceTexture::Create(0);
|
| - gfx::ScopedJavaSurface surface(surface_texture_.get());
|
| + surface_texture_a_ = gfx::SurfaceTexture::Create(0);
|
| + gfx::ScopedJavaSurface surface(surface_texture_a_.get());
|
| +
|
| + ASSERT_NE(nullptr, player_);
|
| + player_->SetVideoSurface(surface.Pass());
|
| +}
|
| +
|
| +void MediaCodecPlayerTest::SetVideoSurfaceB() {
|
| + surface_texture_b_ = gfx::SurfaceTexture::Create(1);
|
| + gfx::ScopedJavaSurface surface(surface_texture_b_.get());
|
|
|
| ASSERT_NE(nullptr, player_);
|
| player_->SetVideoSurface(surface.Pass());
|
| }
|
|
|
| +void MediaCodecPlayerTest::RemoveVideoSurface() {
|
| + player_->SetVideoSurface(gfx::ScopedJavaSurface());
|
| + surface_texture_a_ = NULL;
|
| +}
|
| +
|
| bool MediaCodecPlayerTest::WaitForCondition(const Predicate& condition,
|
| const base::TimeDelta& timeout) {
|
| // Let the message_loop_ process events.
|
| @@ -444,6 +493,33 @@ bool MediaCodecPlayerTest::WaitForPlaybackBeyondPosition(
|
| timeout);
|
| }
|
|
|
| +void MediaCodecPlayerTest::StartVideoPlayback(base::TimeDelta duration) {
|
| + const base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800);
|
| +
|
| + 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();
|
| +
|
| + // Start the player.
|
| + EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| + player_->Start();
|
| +
|
| + // Wait for playback to start.
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| + base::Unretained(&manager_)),
|
| + start_timeout));
|
| +}
|
| +
|
| TEST_F(MediaCodecPlayerTest, SetAudioConfigsBeforePlayerCreation) {
|
| // Post configuration when there is no player yet.
|
| EXPECT_EQ(nullptr, player_);
|
| @@ -552,23 +628,9 @@ TEST_F(MediaCodecPlayerTest, VideoPlayTillCompletion) {
|
| base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
|
| base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1500);
|
|
|
| - 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();
|
| -
|
| - EXPECT_FALSE(manager_.IsPlaybackCompleted());
|
| -
|
| - player_->Start();
|
| + StartVideoPlayback(duration);
|
|
|
| + // Wait till completion.
|
| EXPECT_TRUE(
|
| WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| base::Unretained(&manager_)),
|
| @@ -630,6 +692,10 @@ TEST_F(MediaCodecPlayerTest, AudioSeekAfterStop) {
|
|
|
| // Make sure we started from the beginninig
|
| EXPECT_GT(base::TimeDelta::FromMilliseconds(40), manager_.pts_stat_.min());
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| }
|
|
|
| TEST_F(MediaCodecPlayerTest, AudioSeekThenPlay) {
|
| @@ -660,6 +726,10 @@ TEST_F(MediaCodecPlayerTest, AudioSeekThenPlay) {
|
|
|
| // The playback should start at |seek_position|
|
| EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1));
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| }
|
|
|
| TEST_F(MediaCodecPlayerTest, AudioSeekThenPlayThenConfig) {
|
| @@ -695,6 +765,10 @@ TEST_F(MediaCodecPlayerTest, AudioSeekThenPlayThenConfig) {
|
|
|
| // The playback should start at |seek_position|
|
| EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1));
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| }
|
|
|
| TEST_F(MediaCodecPlayerTest, AudioSeekWhilePlaying) {
|
| @@ -740,6 +814,245 @@ TEST_F(MediaCodecPlayerTest, AudioSeekWhilePlaying) {
|
| // i.e. 200 ms.
|
| EXPECT_TRUE(WaitForPlaybackBeyondPosition(base::TimeDelta::FromSeconds(5)));
|
| EXPECT_TRUE(player_->IsPlaying());
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| +}
|
| +
|
| +TEST_F(MediaCodecPlayerTest, VideoReplaceSurface) {
|
| + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| +
|
| + base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| + base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1500);
|
| +
|
| + StartVideoPlayback(duration);
|
| +
|
| + // Wait for some time and check statistics.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| +
|
| + // Make sure we played at least 100 ms.
|
| + EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| +
|
| + // Set new video surface without removing the old one.
|
| + SetVideoSurfaceB();
|
| +
|
| + // We should receive a browser seek request.
|
| + EXPECT_TRUE(WaitForCondition(
|
| + base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| + base::Unretained(demuxer_))));
|
| +
|
| + // Playback should continue with a new surface. Wait till completion.
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
|
| + base::Unretained(&manager_)),
|
| + timeout));
|
| + EXPECT_LE(duration, manager_.pts_stat_.max());
|
| +}
|
| +
|
| +TEST_F(MediaCodecPlayerTest, VideoRemoveAndSetSurface) {
|
| + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| +
|
| + base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| +
|
| + StartVideoPlayback(duration);
|
| +
|
| + // Wait for some time and check statistics.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| +
|
| + // Make sure we played at least 100 ms.
|
| + EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| +
|
| + // Remove video surface.
|
| + RemoveVideoSurface();
|
| +
|
| + // We should be stuck waiting for the new surface.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| + EXPECT_FALSE(player_->IsPlaying());
|
| +
|
| + // Save last PTS and clear statistics.
|
| + base::TimeDelta max_pts_before_removal = manager_.pts_stat_.max();
|
| + manager_.pts_stat_.Clear();
|
| +
|
| + // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| + EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| +
|
| + // Extra RemoveVideoSurface() should not change anything.
|
| + RemoveVideoSurface();
|
| +
|
| + // Set another video surface.
|
| + SetVideoSurfaceB();
|
| +
|
| + // We should receive a browser seek request.
|
| + EXPECT_TRUE(WaitForCondition(
|
| + base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| + base::Unretained(demuxer_))));
|
| +
|
| + // Playback should continue with a new surface. Wait till it starts again.
|
| + base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| + base::Unretained(&manager_)),
|
| + reconfigure_timeout));
|
| +
|
| + // Timestamps should not go back.
|
| + EXPECT_LE(max_pts_before_removal, manager_.pts_stat_.max());
|
| +}
|
| +
|
| +TEST_F(MediaCodecPlayerTest, VideoReleaseAndStart) {
|
| + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| +
|
| + base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
|
| +
|
| + StartVideoPlayback(duration);
|
| +
|
| + // Wait for some time and check statistics.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| +
|
| + // Make sure we played at least 100 ms.
|
| + EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| +
|
| + // When the user presses Tasks button Chrome calls Pause() and Release().
|
| + player_->Pause(true);
|
| + player_->Release();
|
| +
|
| + // Make sure we are not playing any more.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| + EXPECT_FALSE(player_->IsPlaying());
|
| +
|
| + // Save last PTS and clear statistics.
|
| + base::TimeDelta max_pts_before_backgrounding = manager_.pts_stat_.max();
|
| + manager_.pts_stat_.Clear();
|
| +
|
| + // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| + EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| +
|
| + // Restart.
|
| + SetVideoSurface();
|
| + player_->Start();
|
| +
|
| + // We should receive a browser seek request.
|
| + EXPECT_TRUE(WaitForCondition(
|
| + base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest,
|
| + base::Unretained(demuxer_))));
|
| +
|
| + // Wait for playback to start again.
|
| + base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| + base::Unretained(&manager_)),
|
| + reconfigure_timeout));
|
| +
|
| + // Timestamps should not go back.
|
| + EXPECT_LE(max_pts_before_backgrounding, manager_.pts_stat_.max());
|
| +}
|
| +
|
| +TEST_F(MediaCodecPlayerTest, VideoSeekAndRelease) {
|
| + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| +
|
| + base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| + base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| +
|
| + StartVideoPlayback(duration);
|
| +
|
| + // Wait for some time and check statistics.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| +
|
| + // Make sure we played at least 100 ms.
|
| + EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| +
|
| + // Issue SeekTo() immediately followed by Release().
|
| + player_->SeekTo(seek_position);
|
| + player_->Release();
|
| +
|
| + // Make sure we are not playing any more.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(400));
|
| + EXPECT_FALSE(player_->IsPlaying());
|
| +
|
| + // The Release() should not cancel the SeekTo() and we should have received
|
| + // the seek request by this time.
|
| + EXPECT_TRUE(demuxer_->ReceivedSeekRequest());
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| +
|
| + // Clear statistics.
|
| + manager_.pts_stat_.Clear();
|
| +
|
| + // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| + EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| +
|
| + // Restart.
|
| + SetVideoSurface();
|
| + player_->Start();
|
| +
|
| + // Wait for playback to start again.
|
| + base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(800);
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| + base::Unretained(&manager_)),
|
| + reconfigure_timeout));
|
| +
|
| + // Timestamps should start at the new seek position
|
| + EXPECT_LE(seek_position, manager_.pts_stat_.min());
|
| +}
|
| +
|
| +TEST_F(MediaCodecPlayerTest, VideoReleaseWhileWaitingForSeek) {
|
| + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
|
| +
|
| + base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
|
| + base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000);
|
| +
|
| + StartVideoPlayback(duration);
|
| +
|
| + // Wait for some time and check statistics.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(200));
|
| +
|
| + // Make sure we played at least 100 ms.
|
| + EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_.pts_stat_.max());
|
| +
|
| + // Set artificial delay in the OnDemuxerSeekDone response so we can
|
| + // issue commands while the player is in the STATE_WAITING_FOR_SEEK.
|
| + demuxer_->SetSeekDoneDelay(base::TimeDelta::FromMilliseconds(100));
|
| +
|
| + // Issue SeekTo().
|
| + player_->SeekTo(seek_position);
|
| +
|
| + // Wait for the seek request to demuxer.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockDemuxerAndroid::ReceivedSeekRequest, base::Unretained(demuxer_))));
|
| +
|
| + // The player is supposed to be in STATE_WAITING_FOR_SEEK. Issue Release().
|
| + player_->Release();
|
| +
|
| + // Make sure we are not playing any more.
|
| + WaitForDelay(base::TimeDelta::FromMilliseconds(400));
|
| + EXPECT_FALSE(player_->IsPlaying());
|
| +
|
| + // Clear statistics.
|
| + manager_.pts_stat_.Clear();
|
| +
|
| + // After clearing statistics we are ready to wait for IsPlaybackStarted again.
|
| + EXPECT_FALSE(manager_.IsPlaybackStarted());
|
| +
|
| + // Restart.
|
| + SetVideoSurface();
|
| + player_->Start();
|
| +
|
| + // Wait for playback to start again.
|
| + base::TimeDelta reconfigure_timeout = base::TimeDelta::FromMilliseconds(1000);
|
| + EXPECT_TRUE(
|
| + WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
|
| + base::Unretained(&manager_)),
|
| + reconfigure_timeout));
|
| +
|
| + // Timestamps should start at the new seek position
|
| + EXPECT_LE(seek_position, manager_.pts_stat_.min());
|
| +
|
| + // The player should have reported the seek completion to the manager.
|
| + EXPECT_TRUE(WaitForCondition(base::Bind(
|
| + &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
|
| }
|
|
|
| } // namespace media
|
|
|