1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "base/logging.h"
7 #include "base/timer/timer.h"
8 #include "media/base/android/demuxer_android.h"
9 #include "media/base/android/media_codec_bridge.h"
10 #include "media/base/android/media_codec_player.h"
11 #include "media/base/android/media_player_manager.h"
12 #include "media/base/android/test_data_factory.h"
13 #include "media/base/android/test_statistics.h"
14 #include "media/base/buffers.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gl/android/surface_texture.h"
20 // Helper macro to skip the test if MediaCodecBridge isn't available.
21 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \
23 if (!MediaCodecBridge::IsAvailable()) { \
24 VLOG(0) << "Could not run test - not supported on device."; \
29 #define RUN_ON_MEDIA_THREAD(CLASS, METHOD, ...) \
31 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \
32 GetMediaTaskRunner()->PostTask( \
34 base::Bind(&CLASS::METHOD, base::Unretained(this), ##__VA_ARGS__)); \
41 const base::TimeDelta kDefaultTimeout
= base::TimeDelta::FromMilliseconds(200);
42 const base::TimeDelta kAudioFramePeriod
=
43 base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz
44 const base::TimeDelta kVideoFramePeriod
= base::TimeDelta::FromMilliseconds(20);
46 // The predicate that always returns false, used for WaitForDelay implementation
51 // The method used to compare two TimeDelta values in expectations.
52 bool AlmostEqual(base::TimeDelta a
, base::TimeDelta b
, double tolerance_ms
) {
53 return (a
- b
).magnitude().InMilliseconds() <= tolerance_ms
;
56 // Mock of MediaPlayerManager for testing purpose.
58 class MockMediaPlayerManager
: public MediaPlayerManager
{
60 MockMediaPlayerManager()
61 : playback_completed_(false),
62 num_seeks_completed_(0),
63 weak_ptr_factory_(this) {}
64 ~MockMediaPlayerManager() override
{}
66 MediaResourceGetter
* GetMediaResourceGetter() override
{ return nullptr; }
67 MediaUrlInterceptor
* GetMediaUrlInterceptor() override
{ return nullptr; }
69 void OnTimeUpdate(int player_id
,
70 base::TimeDelta current_timestamp
,
71 base::TimeTicks current_time_ticks
) override
{
72 pts_stat_
.AddValue(current_timestamp
);
75 void OnMediaMetadataChanged(int player_id
,
76 base::TimeDelta duration
,
79 bool success
) override
{
80 media_metadata_
.duration
= duration
;
81 media_metadata_
.width
= width
;
82 media_metadata_
.height
= height
;
83 media_metadata_
.modified
= true;
86 void OnPlaybackComplete(int player_id
) override
{
87 playback_completed_
= true;
90 void OnMediaInterrupted(int player_id
) override
{}
91 void OnBufferingUpdate(int player_id
, int percentage
) override
{}
92 void OnSeekComplete(int player_id
,
93 const base::TimeDelta
& current_time
) override
{
94 ++num_seeks_completed_
;
96 void OnError(int player_id
, int error
) override
{}
97 void OnVideoSizeChanged(int player_id
, int width
, int height
) override
{}
98 void OnAudibleStateChanged(int player_id
, bool is_audible_now
) override
{}
99 void OnWaitingForDecryptionKey(int player_id
) override
{}
100 MediaPlayerAndroid
* GetFullscreenPlayer() override
{ return nullptr; }
101 MediaPlayerAndroid
* GetPlayer(int player_id
) override
{ return nullptr; }
102 bool RequestPlay(int player_id
) override
{ return true; }
104 void OnMediaResourcesRequested(int player_id
) {}
106 base::WeakPtr
<MockMediaPlayerManager
> GetWeakPtr() {
107 return weak_ptr_factory_
.GetWeakPtr();
110 // Conditions to wait for.
111 bool IsMetadataChanged() const { return media_metadata_
.modified
; }
112 bool IsPlaybackCompleted() const { return playback_completed_
; }
113 bool IsPlaybackStarted() const { return pts_stat_
.num_values() > 0; }
114 bool IsPlaybackBeyondPosition(const base::TimeDelta
& pts
) const {
115 return pts_stat_
.max() > pts
;
117 bool IsSeekCompleted() const { return num_seeks_completed_
> 0; }
119 struct MediaMetadata
{
120 base::TimeDelta duration
;
124 MediaMetadata() : width(0), height(0), modified(false) {}
126 MediaMetadata media_metadata_
;
128 Minimax
<base::TimeDelta
> pts_stat_
;
131 bool playback_completed_
;
132 int num_seeks_completed_
;
134 base::WeakPtrFactory
<MockMediaPlayerManager
> weak_ptr_factory_
;
136 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager
);
139 // Helper method that creates demuxer configuration.
141 DemuxerConfigs
CreateAudioVideoConfigs(const base::TimeDelta
& duration
,
142 const gfx::Size
& video_size
) {
143 DemuxerConfigs configs
=
144 TestDataFactory::CreateAudioConfigs(kCodecAAC
, duration
);
145 configs
.video_codec
= kCodecVP8
;
146 configs
.video_size
= video_size
;
147 configs
.is_video_encrypted
= false;
151 DemuxerConfigs
CreateAudioVideoConfigs(const TestDataFactory
* audio
,
152 const TestDataFactory
* video
) {
153 DemuxerConfigs result
= audio
->GetConfigs();
154 DemuxerConfigs vconf
= video
->GetConfigs();
156 result
.video_codec
= vconf
.video_codec
;
157 result
.video_size
= vconf
.video_size
;
158 result
.is_video_encrypted
= vconf
.is_video_encrypted
;
162 // AudioFactory creates data chunks that simulate audio stream from demuxer.
164 class AudioFactory
: public TestDataFactory
{
166 AudioFactory(base::TimeDelta duration
)
167 : TestDataFactory("aac-44100-packet-%d", duration
, kAudioFramePeriod
) {}
169 DemuxerConfigs
GetConfigs() const override
{
170 return TestDataFactory::CreateAudioConfigs(kCodecAAC
, duration_
);
174 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
{
175 unit
->is_key_frame
= true;
179 // VideoFactory creates a video stream from demuxer.
181 class VideoFactory
: public TestDataFactory
{
183 VideoFactory(base::TimeDelta duration
)
184 : TestDataFactory("h264-320x180-frame-%d", duration
, kVideoFramePeriod
),
185 key_frame_requested_(true) {}
187 DemuxerConfigs
GetConfigs() const override
{
188 return TestDataFactory::CreateVideoConfigs(kCodecH264
, duration_
,
189 gfx::Size(320, 180));
192 void RequestKeyFrame() { key_frame_requested_
= true; }
195 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
{
196 // The frames are taken from High profile and some are B-frames.
197 // The first 4 frames appear in the file in the following order:
200 // Decoding order: 0 1 2 3
201 // Presentation order: 0 2 1 4(3)
203 // I keep the last PTS to be 3 for simplicity.
205 // Swap pts for second and third frames. Make first frame a key frame.
206 switch (index_in_chunk
) {
207 case 0: // first frame
208 unit
->is_key_frame
= key_frame_requested_
;
209 key_frame_requested_
= false;
211 case 1: // second frame
212 unit
->timestamp
+= frame_period_
;
214 case 2: // third frame
215 unit
->timestamp
-= frame_period_
;
217 case 3: // fourth frame, do not modify
226 bool key_frame_requested_
;
229 // Mock of DemuxerAndroid for testing purpose.
231 class MockDemuxerAndroid
: public DemuxerAndroid
{
234 : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {}
235 ~MockDemuxerAndroid() override
{}
237 // DemuxerAndroid implementation
238 void Initialize(DemuxerAndroidClient
* client
) override
;
239 void RequestDemuxerData(DemuxerStream::Type type
) override
;
240 void RequestDemuxerSeek(const base::TimeDelta
& time_to_seek
,
241 bool is_browser_seek
) override
;
243 // Sets the audio data factory.
244 void SetAudioFactory(scoped_ptr
<AudioFactory
> factory
) {
245 audio_factory_
= factory
.Pass();
248 // Sets the video data factory.
249 void SetVideoFactory(scoped_ptr
<VideoFactory
> factory
) {
250 video_factory_
= factory
.Pass();
253 // Sets the delay in OnDemuxerSeekDone response.
254 void SetSeekDoneDelay(base::TimeDelta delay
) { seek_done_delay_
= delay
; }
256 // Post DemuxerConfigs to the client (i.e. the player) on correct thread.
257 void PostConfigs(const DemuxerConfigs
& configs
);
259 // Post DemuxerConfigs derived from data factories that has been set.
260 void PostInternalConfigs();
262 // Conditions to wait for.
263 bool IsInitialized() const { return client_
; }
264 bool HasPendingConfigs() const { return pending_configs_
; }
265 bool ReceivedSeekRequest() const { return num_seeks_
> 0; }
266 bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_
> 0; }
269 DemuxerAndroidClient
* client_
;
270 scoped_ptr
<DemuxerConfigs
> pending_configs_
;
271 scoped_ptr
<AudioFactory
> audio_factory_
;
272 scoped_ptr
<VideoFactory
> video_factory_
;
273 base::TimeDelta seek_done_delay_
;
275 int num_browser_seeks_
;
277 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid
);
280 void MockDemuxerAndroid::Initialize(DemuxerAndroidClient
* client
) {
281 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__
;
282 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
285 if (pending_configs_
)
286 client_
->OnDemuxerConfigsAvailable(*pending_configs_
);
289 void MockDemuxerAndroid::RequestDemuxerData(DemuxerStream::Type type
) {
291 base::TimeDelta delay
;
293 bool created
= false;
294 if (type
== DemuxerStream::AUDIO
&& audio_factory_
)
295 created
= audio_factory_
->CreateChunk(&chunk
, &delay
);
296 else if (type
== DemuxerStream::VIDEO
&& video_factory_
)
297 created
= video_factory_
->CreateChunk(&chunk
, &delay
);
304 // Post to Media thread.
306 GetMediaTaskRunner()->PostDelayedTask(
307 FROM_HERE
, base::Bind(&DemuxerAndroidClient::OnDemuxerDataAvailable
,
308 base::Unretained(client_
), chunk
),
312 void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta
& time_to_seek
,
313 bool is_browser_seek
) {
314 // Tell data factories to start next chunk with the new timestamp.
316 audio_factory_
->SeekTo(time_to_seek
);
317 if (video_factory_
) {
318 video_factory_
->SeekTo(time_to_seek
);
319 video_factory_
->RequestKeyFrame();
324 ++num_browser_seeks_
;
326 // Post OnDemuxerSeekDone() to the player.
328 base::TimeDelta reported_seek_time
=
329 is_browser_seek
? time_to_seek
: kNoTimestamp();
330 GetMediaTaskRunner()->PostDelayedTask(
331 FROM_HERE
, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone
,
332 base::Unretained(client_
), reported_seek_time
),
336 void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs
& configs
) {
337 RUN_ON_MEDIA_THREAD(MockDemuxerAndroid
, PostConfigs
, configs
);
339 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__
;
341 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
344 client_
->OnDemuxerConfigsAvailable(configs
);
346 pending_configs_
= scoped_ptr
<DemuxerConfigs
>(new DemuxerConfigs(configs
));
349 void MockDemuxerAndroid::PostInternalConfigs() {
350 ASSERT_TRUE(audio_factory_
|| video_factory_
);
352 if (audio_factory_
&& video_factory_
) {
354 CreateAudioVideoConfigs(audio_factory_
.get(), video_factory_
.get()));
355 } else if (audio_factory_
) {
356 PostConfigs(audio_factory_
->GetConfigs());
357 } else if (video_factory_
) {
358 PostConfigs(video_factory_
->GetConfigs());
362 } // namespace (anonymous)
364 // The test fixture for MediaCodecPlayer
366 class MediaCodecPlayerTest
: public testing::Test
{
368 MediaCodecPlayerTest();
369 ~MediaCodecPlayerTest() override
;
371 // Conditions to wait for.
372 bool IsPaused() const { return !(player_
&& player_
->IsPlaying()); }
375 typedef base::Callback
<bool()> Predicate
;
378 void SetVideoSurface();
379 void SetVideoSurfaceB();
380 void RemoveVideoSurface();
382 // Waits for condition to become true or for timeout to expire.
383 // Returns true if the condition becomes true.
384 bool WaitForCondition(const Predicate
& condition
,
385 const base::TimeDelta
& timeout
= kDefaultTimeout
);
387 // Waits for timeout to expire.
388 void WaitForDelay(const base::TimeDelta
& timeout
);
390 // Waits till playback position as determined by maximal reported pts
391 // reaches the given value or for timeout to expire. Returns true if the
392 // playback has passed the given position.
393 bool WaitForPlaybackBeyondPosition(
394 const base::TimeDelta
& pts
,
395 const base::TimeDelta
& timeout
= kDefaultTimeout
);
397 // Helper method that starts video only stream. Waits till it actually
399 void StartVideoPlayback(base::TimeDelta duration
);
401 base::MessageLoop message_loop_
;
402 MockMediaPlayerManager manager_
;
403 MockDemuxerAndroid
* demuxer_
; // owned by player_
404 scoped_refptr
<gfx::SurfaceTexture
> surface_texture_a_
;
405 scoped_refptr
<gfx::SurfaceTexture
> surface_texture_b_
;
406 MediaCodecPlayer
* player_
; // raw pointer due to DeleteOnCorrectThread()
409 bool is_timeout_expired() const { return is_timeout_expired_
; }
410 void SetTimeoutExpired(bool value
) { is_timeout_expired_
= value
; }
412 bool is_timeout_expired_
;
414 DISALLOW_COPY_AND_ASSIGN(MediaCodecPlayerTest
);
417 MediaCodecPlayerTest::MediaCodecPlayerTest()
418 : demuxer_(new MockDemuxerAndroid()), player_(nullptr) {
421 MediaCodecPlayerTest::~MediaCodecPlayerTest() {
423 player_
->DeleteOnCorrectThread();
426 void MediaCodecPlayerTest::CreatePlayer() {
428 player_
= new MediaCodecPlayer(
430 manager_
.GetWeakPtr(),
431 base::Bind(&MockMediaPlayerManager::OnMediaResourcesRequested
,
432 base::Unretained(&manager_
)),
433 scoped_ptr
<MockDemuxerAndroid
>(demuxer_
), GURL());
438 void MediaCodecPlayerTest::SetVideoSurface() {
439 surface_texture_a_
= gfx::SurfaceTexture::Create(0);
440 gfx::ScopedJavaSurface
surface(surface_texture_a_
.get());
442 ASSERT_NE(nullptr, player_
);
443 player_
->SetVideoSurface(surface
.Pass());
446 void MediaCodecPlayerTest::SetVideoSurfaceB() {
447 surface_texture_b_
= gfx::SurfaceTexture::Create(1);
448 gfx::ScopedJavaSurface
surface(surface_texture_b_
.get());
450 ASSERT_NE(nullptr, player_
);
451 player_
->SetVideoSurface(surface
.Pass());
454 void MediaCodecPlayerTest::RemoveVideoSurface() {
455 player_
->SetVideoSurface(gfx::ScopedJavaSurface());
456 surface_texture_a_
= NULL
;
459 bool MediaCodecPlayerTest::WaitForCondition(const Predicate
& condition
,
460 const base::TimeDelta
& timeout
) {
461 // Let the message_loop_ process events.
462 // We start the timer and RunUntilIdle() until it signals.
464 SetTimeoutExpired(false);
466 base::Timer
timer(false, false);
467 timer
.Start(FROM_HERE
, timeout
,
468 base::Bind(&MediaCodecPlayerTest::SetTimeoutExpired
,
469 base::Unretained(this), true));
472 if (condition
.Run()) {
476 message_loop_
.RunUntilIdle();
477 } while (!is_timeout_expired());
479 DCHECK(!timer
.IsRunning());
483 void MediaCodecPlayerTest::WaitForDelay(const base::TimeDelta
& timeout
) {
484 WaitForCondition(base::Bind(&AlwaysFalse
), timeout
);
487 bool MediaCodecPlayerTest::WaitForPlaybackBeyondPosition(
488 const base::TimeDelta
& pts
,
489 const base::TimeDelta
& timeout
) {
490 return WaitForCondition(
491 base::Bind(&MockMediaPlayerManager::IsPlaybackBeyondPosition
,
492 base::Unretained(&manager_
), pts
),
496 void MediaCodecPlayerTest::StartVideoPlayback(base::TimeDelta duration
) {
497 const base::TimeDelta start_timeout
= base::TimeDelta::FromMilliseconds(800);
499 demuxer_
->SetVideoFactory(
500 scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
505 // Wait till the player is initialized on media thread.
506 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized
,
507 base::Unretained(demuxer_
))));
509 // Post configuration after the player has been initialized.
510 demuxer_
->PostInternalConfigs();
513 EXPECT_FALSE(manager_
.IsPlaybackStarted());
516 // Wait for playback to start.
518 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
519 base::Unretained(&manager_
)),
523 TEST_F(MediaCodecPlayerTest
, SetAudioConfigsBeforePlayerCreation
) {
524 // Post configuration when there is no player yet.
525 EXPECT_EQ(nullptr, player_
);
527 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
529 demuxer_
->PostConfigs(
530 TestDataFactory::CreateAudioConfigs(kCodecAAC
, duration
));
532 // Wait until the configuration gets to the media thread.
533 EXPECT_TRUE(WaitForCondition(base::Bind(
534 &MockDemuxerAndroid::HasPendingConfigs
, base::Unretained(demuxer_
))));
536 // Then create the player.
539 // Configuration should propagate through the player and to the manager.
541 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged
,
542 base::Unretained(&manager_
))));
544 EXPECT_EQ(duration
, manager_
.media_metadata_
.duration
);
545 EXPECT_EQ(0, manager_
.media_metadata_
.width
);
546 EXPECT_EQ(0, manager_
.media_metadata_
.height
);
549 TEST_F(MediaCodecPlayerTest
, SetAudioConfigsAfterPlayerCreation
) {
552 // Wait till the player is initialized on media thread.
553 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized
,
554 base::Unretained(demuxer_
))));
556 // Post configuration after the player has been initialized.
557 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
558 demuxer_
->PostConfigs(
559 TestDataFactory::CreateAudioConfigs(kCodecAAC
, duration
));
561 // Configuration should propagate through the player and to the manager.
563 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged
,
564 base::Unretained(&manager_
))));
566 EXPECT_EQ(duration
, manager_
.media_metadata_
.duration
);
567 EXPECT_EQ(0, manager_
.media_metadata_
.width
);
568 EXPECT_EQ(0, manager_
.media_metadata_
.height
);
571 TEST_F(MediaCodecPlayerTest
, SetAudioVideoConfigsAfterPlayerCreation
) {
574 // Wait till the player is initialized on media thread.
575 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized
,
576 base::Unretained(demuxer_
))));
578 // Post configuration after the player has been initialized.
579 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
580 demuxer_
->PostConfigs(CreateAudioVideoConfigs(duration
, gfx::Size(320, 240)));
582 // Configuration should propagate through the player and to the manager.
584 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsMetadataChanged
,
585 base::Unretained(&manager_
))));
587 EXPECT_EQ(duration
, manager_
.media_metadata_
.duration
);
588 EXPECT_EQ(320, manager_
.media_metadata_
.width
);
589 EXPECT_EQ(240, manager_
.media_metadata_
.height
);
592 TEST_F(MediaCodecPlayerTest
, AudioPlayTillCompletion
) {
593 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
595 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(1000);
596 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(2000);
598 demuxer_
->SetAudioFactory(
599 scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
603 // Wait till the player is initialized on media thread.
604 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized
,
605 base::Unretained(demuxer_
))));
607 // Post configuration after the player has been initialized.
608 demuxer_
->PostInternalConfigs();
610 EXPECT_FALSE(manager_
.IsPlaybackCompleted());
615 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted
,
616 base::Unretained(&manager_
)),
619 // Current timestamp reflects "now playing" time. It might come with delay
620 // relative to the frame's PTS. Allow for 100 ms delay here.
621 base::TimeDelta audio_pts_delay
= base::TimeDelta::FromMilliseconds(100);
622 EXPECT_LT(duration
- audio_pts_delay
, manager_
.pts_stat_
.max());
625 TEST_F(MediaCodecPlayerTest
, VideoPlayTillCompletion
) {
626 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
628 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
629 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1500);
631 StartVideoPlayback(duration
);
633 // Wait till completion.
635 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted
,
636 base::Unretained(&manager_
)),
639 EXPECT_LE(duration
, manager_
.pts_stat_
.max());
642 // http://crbug.com/518900
643 TEST_F(MediaCodecPlayerTest
, DISABLED_AudioSeekAfterStop
) {
644 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
646 // Play for 300 ms, then Pause, then Seek to beginning. The playback should
647 // start from the beginning.
649 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(2000);
651 demuxer_
->SetAudioFactory(
652 scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
656 // Post configuration.
657 demuxer_
->PostInternalConfigs();
662 // Wait for playback to start.
664 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
665 base::Unretained(&manager_
))));
667 // Wait for 300 ms and stop. The 300 ms interval takes into account potential
668 // audio delay: audio takes time reconfiguring after the first several packets
669 // get written to the audio track.
670 WaitForDelay(base::TimeDelta::FromMilliseconds(300));
672 player_
->Pause(true);
674 // Make sure we played at least 100 ms.
675 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
677 // Wait till the Pause is completed.
678 EXPECT_TRUE(WaitForCondition(
679 base::Bind(&MediaCodecPlayerTest::IsPaused
, base::Unretained(this))));
682 manager_
.pts_stat_
.Clear();
684 // Now we can seek to the beginning and start the playback.
685 player_
->SeekTo(base::TimeDelta());
689 // Wait for playback to start.
691 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
692 base::Unretained(&manager_
))));
694 // Make sure we started from the beginninig
695 EXPECT_GT(base::TimeDelta::FromMilliseconds(40), manager_
.pts_stat_
.min());
697 // The player should have reported the seek completion to the manager.
698 EXPECT_TRUE(WaitForCondition(base::Bind(
699 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
702 TEST_F(MediaCodecPlayerTest
, AudioSeekThenPlay
) {
703 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
705 // Issue Seek command immediately followed by Start. The playback should
706 // start at the seek position.
708 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(2000);
709 base::TimeDelta seek_position
= base::TimeDelta::FromMilliseconds(500);
711 demuxer_
->SetAudioFactory(
712 scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
716 // Post configuration.
717 demuxer_
->PostInternalConfigs();
719 // Seek and immediately start.
720 player_
->SeekTo(seek_position
);
723 // Wait for playback to start.
725 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
726 base::Unretained(&manager_
))));
728 // The playback should start at |seek_position|
729 EXPECT_TRUE(AlmostEqual(seek_position
, manager_
.pts_stat_
.min(), 1));
731 // The player should have reported the seek completion to the manager.
732 EXPECT_TRUE(WaitForCondition(base::Bind(
733 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
736 TEST_F(MediaCodecPlayerTest
, AudioSeekThenPlayThenConfig
) {
737 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
739 // Issue Seek command immediately followed by Start but without prior demuxer
740 // configuration. Start should wait for configuration. After it has been
741 // posted the playback should start at the seek position.
743 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(2000);
744 base::TimeDelta seek_position
= base::TimeDelta::FromMilliseconds(500);
746 demuxer_
->SetAudioFactory(
747 scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
751 // Seek and immediately start.
752 player_
->SeekTo(seek_position
);
755 // Make sure the player is waiting.
756 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
757 EXPECT_FALSE(player_
->IsPlaying());
759 // Post configuration.
760 demuxer_
->PostInternalConfigs();
762 // Wait for playback to start.
764 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
765 base::Unretained(&manager_
))));
767 // The playback should start at |seek_position|
768 EXPECT_TRUE(AlmostEqual(seek_position
, manager_
.pts_stat_
.min(), 1));
770 // The player should have reported the seek completion to the manager.
771 EXPECT_TRUE(WaitForCondition(base::Bind(
772 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
775 // http://crbug.com/518900
776 TEST_F(MediaCodecPlayerTest
, DISABLED_AudioSeekWhilePlaying
) {
777 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
779 // Play for 300 ms, then issue several Seek commands in the row.
780 // The playback should continue at the last seek position.
782 // To test this condition without analyzing the reported time details
783 // and without introducing dependency on implementation I make a long (10s)
784 // duration and test that the playback resumes after big time jump (5s) in a
785 // short period of time (200 ms).
786 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
788 demuxer_
->SetAudioFactory(
789 scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
793 // Post configuration.
794 demuxer_
->PostInternalConfigs();
799 // Wait for playback to start.
801 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
802 base::Unretained(&manager_
))));
805 WaitForDelay(base::TimeDelta::FromMilliseconds(300));
807 // Make sure we played at least 100 ms.
808 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
810 // Seek forward several times.
811 player_
->SeekTo(base::TimeDelta::FromSeconds(3));
812 player_
->SeekTo(base::TimeDelta::FromSeconds(4));
813 player_
->SeekTo(base::TimeDelta::FromSeconds(5));
815 // Make sure that we reached the last timestamp within default timeout,
817 EXPECT_TRUE(WaitForPlaybackBeyondPosition(base::TimeDelta::FromSeconds(5)));
818 EXPECT_TRUE(player_
->IsPlaying());
820 // The player should have reported the seek completion to the manager.
821 EXPECT_TRUE(WaitForCondition(base::Bind(
822 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
825 TEST_F(MediaCodecPlayerTest
, VideoReplaceSurface
) {
826 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
828 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(1000);
829 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1500);
831 StartVideoPlayback(duration
);
833 // Wait for some time and check statistics.
834 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
836 // Make sure we played at least 100 ms.
837 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
839 // Set new video surface without removing the old one.
842 // We should receive a browser seek request.
843 EXPECT_TRUE(WaitForCondition(
844 base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest
,
845 base::Unretained(demuxer_
))));
847 // Playback should continue with a new surface. Wait till completion.
849 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted
,
850 base::Unretained(&manager_
)),
852 EXPECT_LE(duration
, manager_
.pts_stat_
.max());
855 TEST_F(MediaCodecPlayerTest
, VideoRemoveAndSetSurface
) {
856 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
858 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(1000);
860 StartVideoPlayback(duration
);
862 // Wait for some time and check statistics.
863 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
865 // Make sure we played at least 100 ms.
866 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
868 // Remove video surface.
869 RemoveVideoSurface();
871 // We should be stuck waiting for the new surface.
872 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
873 EXPECT_FALSE(player_
->IsPlaying());
875 // Save last PTS and clear statistics.
876 base::TimeDelta max_pts_before_removal
= manager_
.pts_stat_
.max();
877 manager_
.pts_stat_
.Clear();
879 // After clearing statistics we are ready to wait for IsPlaybackStarted again.
880 EXPECT_FALSE(manager_
.IsPlaybackStarted());
882 // Extra RemoveVideoSurface() should not change anything.
883 RemoveVideoSurface();
885 // Set another video surface.
888 // We should receive a browser seek request.
889 EXPECT_TRUE(WaitForCondition(
890 base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest
,
891 base::Unretained(demuxer_
))));
893 // Playback should continue with a new surface. Wait till it starts again.
894 base::TimeDelta reconfigure_timeout
= base::TimeDelta::FromMilliseconds(800);
896 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
897 base::Unretained(&manager_
)),
898 reconfigure_timeout
));
900 // Timestamps should not go back.
901 EXPECT_LE(max_pts_before_removal
, manager_
.pts_stat_
.max());
904 // http://crbug.com/518900
905 TEST_F(MediaCodecPlayerTest
, DISABLED_VideoReleaseAndStart
) {
906 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
908 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(1000);
910 StartVideoPlayback(duration
);
912 // Wait for some time and check statistics.
913 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
915 // Make sure we played at least 100 ms.
916 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
918 // When the user presses Tasks button Chrome calls Pause() and Release().
919 player_
->Pause(true);
922 // Make sure we are not playing any more.
923 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
924 EXPECT_FALSE(player_
->IsPlaying());
926 // Save last PTS and clear statistics.
927 base::TimeDelta max_pts_before_backgrounding
= manager_
.pts_stat_
.max();
928 manager_
.pts_stat_
.Clear();
930 // After clearing statistics we are ready to wait for IsPlaybackStarted again.
931 EXPECT_FALSE(manager_
.IsPlaybackStarted());
937 // We should receive a browser seek request.
938 EXPECT_TRUE(WaitForCondition(
939 base::Bind(&MockDemuxerAndroid::ReceivedBrowserSeekRequest
,
940 base::Unretained(demuxer_
))));
942 // Wait for playback to start again.
943 base::TimeDelta reconfigure_timeout
= base::TimeDelta::FromMilliseconds(800);
945 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
946 base::Unretained(&manager_
)),
947 reconfigure_timeout
));
949 // Timestamps should not go back.
950 EXPECT_LE(max_pts_before_backgrounding
, manager_
.pts_stat_
.max());
953 TEST_F(MediaCodecPlayerTest
, VideoSeekAndRelease
) {
954 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
956 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(2000);
957 base::TimeDelta seek_position
= base::TimeDelta::FromMilliseconds(1000);
959 StartVideoPlayback(duration
);
961 // Wait for some time and check statistics.
962 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
964 // Make sure we played at least 100 ms.
965 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
967 // Issue SeekTo() immediately followed by Release().
968 player_
->SeekTo(seek_position
);
971 // Make sure we are not playing any more.
972 WaitForDelay(base::TimeDelta::FromMilliseconds(400));
973 EXPECT_FALSE(player_
->IsPlaying());
975 // The Release() should not cancel the SeekTo() and we should have received
976 // the seek request by this time.
977 EXPECT_TRUE(demuxer_
->ReceivedSeekRequest());
979 // The player should have reported the seek completion to the manager.
980 EXPECT_TRUE(WaitForCondition(base::Bind(
981 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
984 manager_
.pts_stat_
.Clear();
986 // After clearing statistics we are ready to wait for IsPlaybackStarted again.
987 EXPECT_FALSE(manager_
.IsPlaybackStarted());
993 // Wait for playback to start again.
994 base::TimeDelta reconfigure_timeout
= base::TimeDelta::FromMilliseconds(800);
996 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
997 base::Unretained(&manager_
)),
998 reconfigure_timeout
));
1000 // Timestamps should start at the new seek position
1001 EXPECT_LE(seek_position
, manager_
.pts_stat_
.min());
1004 TEST_F(MediaCodecPlayerTest
, VideoReleaseWhileWaitingForSeek
) {
1005 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
1007 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(2000);
1008 base::TimeDelta seek_position
= base::TimeDelta::FromMilliseconds(1000);
1010 StartVideoPlayback(duration
);
1012 // Wait for some time and check statistics.
1013 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
1015 // Make sure we played at least 100 ms.
1016 EXPECT_LT(base::TimeDelta::FromMilliseconds(100), manager_
.pts_stat_
.max());
1018 // Set artificial delay in the OnDemuxerSeekDone response so we can
1019 // issue commands while the player is in the STATE_WAITING_FOR_SEEK.
1020 demuxer_
->SetSeekDoneDelay(base::TimeDelta::FromMilliseconds(100));
1023 player_
->SeekTo(seek_position
);
1025 // Wait for the seek request to demuxer.
1026 EXPECT_TRUE(WaitForCondition(base::Bind(
1027 &MockDemuxerAndroid::ReceivedSeekRequest
, base::Unretained(demuxer_
))));
1029 // The player is supposed to be in STATE_WAITING_FOR_SEEK. Issue Release().
1032 // Make sure we are not playing any more.
1033 WaitForDelay(base::TimeDelta::FromMilliseconds(400));
1034 EXPECT_FALSE(player_
->IsPlaying());
1036 // Clear statistics.
1037 manager_
.pts_stat_
.Clear();
1039 // After clearing statistics we are ready to wait for IsPlaybackStarted again.
1040 EXPECT_FALSE(manager_
.IsPlaybackStarted());
1046 // Wait for playback to start again.
1047 base::TimeDelta reconfigure_timeout
= base::TimeDelta::FromMilliseconds(1000);
1049 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted
,
1050 base::Unretained(&manager_
)),
1051 reconfigure_timeout
));
1053 // Timestamps should start at the new seek position
1054 EXPECT_LE(seek_position
, manager_
.pts_stat_
.min());
1056 // The player should have reported the seek completion to the manager.
1057 EXPECT_TRUE(WaitForCondition(base::Bind(
1058 &MockMediaPlayerManager::IsSeekCompleted
, base::Unretained(&manager_
))));
1061 } // namespace media