OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/timer/timer.h" | 7 #include "base/timer/timer.h" |
8 #include "media/base/android/demuxer_android.h" | 8 #include "media/base/android/demuxer_android.h" |
9 #include "media/base/android/media_codec_bridge.h" | 9 #include "media/base/android/media_codec_bridge.h" |
10 #include "media/base/android/media_codec_player.h" | 10 #include "media/base/android/media_codec_player.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200); | 41 const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200); |
42 const base::TimeDelta kAudioFramePeriod = | 42 const base::TimeDelta kAudioFramePeriod = |
43 base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz | 43 base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz |
44 const base::TimeDelta kVideoFramePeriod = base::TimeDelta::FromMilliseconds(20); | 44 const base::TimeDelta kVideoFramePeriod = base::TimeDelta::FromMilliseconds(20); |
45 | 45 |
46 // The predicate that always returns false, used for WaitForDelay implementation | 46 // The predicate that always returns false, used for WaitForDelay implementation |
47 bool AlwaysFalse() { | 47 bool AlwaysFalse() { |
48 return false; | 48 return false; |
49 } | 49 } |
50 | 50 |
51 // The method used to compare two TimeDelta values in expectations. | 51 // The method used to compare two time values of type T in expectations. |
52 bool AlmostEqual(base::TimeDelta a, base::TimeDelta b, double tolerance_ms) { | 52 // Type T requires that a difference of type base::TimeDelta is defined. |
| 53 template <typename T> |
| 54 bool AlmostEqual(T a, T b, double tolerance_ms) { |
53 return (a - b).magnitude().InMilliseconds() <= tolerance_ms; | 55 return (a - b).magnitude().InMilliseconds() <= tolerance_ms; |
54 } | 56 } |
55 | 57 |
56 // Mock of MediaPlayerManager for testing purpose. | 58 // Mock of MediaPlayerManager for testing purpose. |
57 | 59 |
58 class MockMediaPlayerManager : public MediaPlayerManager { | 60 class MockMediaPlayerManager : public MediaPlayerManager { |
59 public: | 61 public: |
60 MockMediaPlayerManager() | 62 MockMediaPlayerManager() |
61 : playback_completed_(false), | 63 : playback_completed_(false), |
62 num_seeks_completed_(0), | 64 num_seeks_completed_(0), |
63 weak_ptr_factory_(this) {} | 65 weak_ptr_factory_(this) {} |
64 ~MockMediaPlayerManager() override {} | 66 ~MockMediaPlayerManager() override {} |
65 | 67 |
66 MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; } | 68 MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; } |
67 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return nullptr; } | 69 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return nullptr; } |
68 | 70 |
| 71 // Regular time update callback, reports current playback time to |
| 72 // MediaPlayerManager. |
69 void OnTimeUpdate(int player_id, | 73 void OnTimeUpdate(int player_id, |
70 base::TimeDelta current_timestamp, | 74 base::TimeDelta current_timestamp, |
71 base::TimeTicks current_time_ticks) override { | 75 base::TimeTicks current_time_ticks) override { |
72 pts_stat_.AddValue(current_timestamp); | 76 pts_stat_.AddValue(current_timestamp); |
73 } | 77 } |
74 | 78 |
75 void OnMediaMetadataChanged(int player_id, | 79 void OnMediaMetadataChanged(int player_id, |
76 base::TimeDelta duration, | 80 base::TimeDelta duration, |
77 int width, | 81 int width, |
78 int height, | 82 int height, |
(...skipping 17 matching lines...) Expand all Loading... |
96 void OnError(int player_id, int error) override {} | 100 void OnError(int player_id, int error) override {} |
97 void OnVideoSizeChanged(int player_id, int width, int height) override {} | 101 void OnVideoSizeChanged(int player_id, int width, int height) override {} |
98 void OnAudibleStateChanged(int player_id, bool is_audible_now) override {} | 102 void OnAudibleStateChanged(int player_id, bool is_audible_now) override {} |
99 void OnWaitingForDecryptionKey(int player_id) override {} | 103 void OnWaitingForDecryptionKey(int player_id) override {} |
100 MediaPlayerAndroid* GetFullscreenPlayer() override { return nullptr; } | 104 MediaPlayerAndroid* GetFullscreenPlayer() override { return nullptr; } |
101 MediaPlayerAndroid* GetPlayer(int player_id) override { return nullptr; } | 105 MediaPlayerAndroid* GetPlayer(int player_id) override { return nullptr; } |
102 bool RequestPlay(int player_id) override { return true; } | 106 bool RequestPlay(int player_id) override { return true; } |
103 | 107 |
104 void OnMediaResourcesRequested(int player_id) {} | 108 void OnMediaResourcesRequested(int player_id) {} |
105 | 109 |
| 110 // Time update callback that reports the internal progress of the stream. |
| 111 // Implementation dependent, used for testing only. |
| 112 void OnDecodersTimeUpdate(DemuxerStream::Type stream_type, |
| 113 base::TimeDelta now_playing, |
| 114 base::TimeDelta last_buffered) { |
| 115 PTSTime& hit = first_frame_hit_[stream_type]; |
| 116 if (hit.is_null()) |
| 117 hit = PTSTime(now_playing, base::TimeTicks::Now()); |
| 118 } |
| 119 |
| 120 // First frame information |
| 121 base::TimeDelta FirstFramePTS(DemuxerStream::Type stream_type) const { |
| 122 return first_frame_hit_[stream_type].pts; |
| 123 } |
| 124 base::TimeTicks FirstFrameTime(DemuxerStream::Type stream_type) const { |
| 125 return first_frame_hit_[stream_type].time; |
| 126 } |
| 127 |
106 base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() { | 128 base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() { |
107 return weak_ptr_factory_.GetWeakPtr(); | 129 return weak_ptr_factory_.GetWeakPtr(); |
108 } | 130 } |
109 | 131 |
110 // Conditions to wait for. | 132 // Conditions to wait for. |
111 bool IsMetadataChanged() const { return media_metadata_.modified; } | 133 bool IsMetadataChanged() const { return media_metadata_.modified; } |
112 bool IsPlaybackCompleted() const { return playback_completed_; } | 134 bool IsPlaybackCompleted() const { return playback_completed_; } |
113 bool IsPlaybackStarted() const { return pts_stat_.num_values() > 0; } | 135 bool IsPlaybackStarted() const { return pts_stat_.num_values() > 0; } |
114 bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const { | 136 bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const { |
115 return pts_stat_.max() > pts; | 137 return pts_stat_.max() > pts; |
116 } | 138 } |
117 bool IsSeekCompleted() const { return num_seeks_completed_ > 0; } | 139 bool IsSeekCompleted() const { return num_seeks_completed_ > 0; } |
| 140 bool HasFirstFrame(DemuxerStream::Type stream_type) const { |
| 141 return !first_frame_hit_[stream_type].is_null(); |
| 142 } |
118 | 143 |
119 struct MediaMetadata { | 144 struct MediaMetadata { |
120 base::TimeDelta duration; | 145 base::TimeDelta duration; |
121 int width; | 146 int width; |
122 int height; | 147 int height; |
123 bool modified; | 148 bool modified; |
124 MediaMetadata() : width(0), height(0), modified(false) {} | 149 MediaMetadata() : width(0), height(0), modified(false) {} |
125 }; | 150 }; |
126 MediaMetadata media_metadata_; | 151 MediaMetadata media_metadata_; |
127 | 152 |
128 Minimax<base::TimeDelta> pts_stat_; | 153 Minimax<base::TimeDelta> pts_stat_; |
129 | 154 |
130 private: | 155 private: |
131 bool playback_completed_; | 156 bool playback_completed_; |
132 int num_seeks_completed_; | 157 int num_seeks_completed_; |
133 | 158 |
| 159 struct PTSTime { |
| 160 base::TimeDelta pts; |
| 161 base::TimeTicks time; |
| 162 PTSTime() : pts(), time() {} |
| 163 PTSTime(base::TimeDelta p, base::TimeTicks t) : pts(p), time(t) {} |
| 164 bool is_null() const { return time.is_null(); } |
| 165 }; |
| 166 PTSTime first_frame_hit_[DemuxerStream::NUM_TYPES]; |
| 167 |
134 base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_; | 168 base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_; |
135 | 169 |
136 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); | 170 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); |
137 }; | 171 }; |
138 | 172 |
139 // Helper method that creates demuxer configuration. | 173 // Helper method that creates demuxer configuration. |
140 | 174 |
141 DemuxerConfigs CreateAudioVideoConfigs(const base::TimeDelta& duration, | 175 DemuxerConfigs CreateAudioVideoConfigs(const base::TimeDelta& duration, |
142 const gfx::Size& video_size) { | 176 const gfx::Size& video_size) { |
143 DemuxerConfigs configs = | 177 DemuxerConfigs configs = |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 | 264 |
231 class MockDemuxerAndroid : public DemuxerAndroid { | 265 class MockDemuxerAndroid : public DemuxerAndroid { |
232 public: | 266 public: |
233 MockDemuxerAndroid() | 267 MockDemuxerAndroid() |
234 : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {} | 268 : client_(nullptr), num_seeks_(0), num_browser_seeks_(0) {} |
235 ~MockDemuxerAndroid() override {} | 269 ~MockDemuxerAndroid() override {} |
236 | 270 |
237 // DemuxerAndroid implementation | 271 // DemuxerAndroid implementation |
238 void Initialize(DemuxerAndroidClient* client) override; | 272 void Initialize(DemuxerAndroidClient* client) override; |
239 void RequestDemuxerData(DemuxerStream::Type type) override; | 273 void RequestDemuxerData(DemuxerStream::Type type) override; |
240 void RequestDemuxerSeek(const base::TimeDelta& time_to_seek, | 274 void RequestDemuxerSeek(const base::TimeDelta& seek_request, |
241 bool is_browser_seek) override; | 275 bool is_browser_seek) override; |
242 | 276 |
243 // Sets the audio data factory. | 277 // Sets the audio data factory. |
244 void SetAudioFactory(scoped_ptr<AudioFactory> factory) { | 278 void SetAudioFactory(scoped_ptr<AudioFactory> factory) { |
245 audio_factory_ = factory.Pass(); | 279 audio_factory_ = factory.Pass(); |
246 } | 280 } |
247 | 281 |
248 // Sets the video data factory. | 282 // Sets the video data factory. |
249 void SetVideoFactory(scoped_ptr<VideoFactory> factory) { | 283 void SetVideoFactory(scoped_ptr<VideoFactory> factory) { |
250 video_factory_ = factory.Pass(); | 284 video_factory_ = factory.Pass(); |
251 } | 285 } |
252 | 286 |
| 287 // Accessors for data factories. |
| 288 AudioFactory* audio_factory() const { return audio_factory_.get(); } |
| 289 VideoFactory* video_factory() const { return video_factory_.get(); } |
| 290 |
| 291 // Set the preroll interval after seek for audio stream. |
| 292 void SetAudioPrerollInterval(base::TimeDelta value) { |
| 293 audio_preroll_interval_ = value; |
| 294 } |
| 295 |
| 296 // Set the preroll interval after seek for video stream. |
| 297 void SetVideoPrerollInterval(base::TimeDelta value) { |
| 298 video_preroll_interval_ = value; |
| 299 } |
| 300 |
253 // Sets the delay in OnDemuxerSeekDone response. | 301 // Sets the delay in OnDemuxerSeekDone response. |
254 void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; } | 302 void SetSeekDoneDelay(base::TimeDelta delay) { seek_done_delay_ = delay; } |
255 | 303 |
256 // Post DemuxerConfigs to the client (i.e. the player) on correct thread. | 304 // Post DemuxerConfigs to the client (i.e. the player) on correct thread. |
257 void PostConfigs(const DemuxerConfigs& configs); | 305 void PostConfigs(const DemuxerConfigs& configs); |
258 | 306 |
259 // Post DemuxerConfigs derived from data factories that has been set. | 307 // Post DemuxerConfigs derived from data factories that has been set. |
260 void PostInternalConfigs(); | 308 void PostInternalConfigs(); |
261 | 309 |
262 // Conditions to wait for. | 310 // Conditions to wait for. |
263 bool IsInitialized() const { return client_; } | 311 bool IsInitialized() const { return client_; } |
264 bool HasPendingConfigs() const { return pending_configs_; } | 312 bool HasPendingConfigs() const { return pending_configs_; } |
265 bool ReceivedSeekRequest() const { return num_seeks_ > 0; } | 313 bool ReceivedSeekRequest() const { return num_seeks_ > 0; } |
266 bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; } | 314 bool ReceivedBrowserSeekRequest() const { return num_browser_seeks_ > 0; } |
267 | 315 |
268 private: | 316 private: |
269 DemuxerAndroidClient* client_; | 317 DemuxerAndroidClient* client_; |
270 scoped_ptr<DemuxerConfigs> pending_configs_; | 318 scoped_ptr<DemuxerConfigs> pending_configs_; |
271 scoped_ptr<AudioFactory> audio_factory_; | 319 scoped_ptr<AudioFactory> audio_factory_; |
272 scoped_ptr<VideoFactory> video_factory_; | 320 scoped_ptr<VideoFactory> video_factory_; |
| 321 base::TimeDelta audio_preroll_interval_; |
| 322 base::TimeDelta video_preroll_interval_; |
273 base::TimeDelta seek_done_delay_; | 323 base::TimeDelta seek_done_delay_; |
274 int num_seeks_; | 324 int num_seeks_; |
275 int num_browser_seeks_; | 325 int num_browser_seeks_; |
276 | 326 |
277 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); | 327 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); |
278 }; | 328 }; |
279 | 329 |
280 void MockDemuxerAndroid::Initialize(DemuxerAndroidClient* client) { | 330 void MockDemuxerAndroid::Initialize(DemuxerAndroidClient* client) { |
281 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; | 331 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; |
282 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 332 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
(...skipping 19 matching lines...) Expand all Loading... |
302 chunk.type = type; | 352 chunk.type = type; |
303 | 353 |
304 // Post to Media thread. | 354 // Post to Media thread. |
305 DCHECK(client_); | 355 DCHECK(client_); |
306 GetMediaTaskRunner()->PostDelayedTask( | 356 GetMediaTaskRunner()->PostDelayedTask( |
307 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerDataAvailable, | 357 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerDataAvailable, |
308 base::Unretained(client_), chunk), | 358 base::Unretained(client_), chunk), |
309 delay); | 359 delay); |
310 } | 360 } |
311 | 361 |
312 void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& time_to_seek, | 362 void MockDemuxerAndroid::RequestDemuxerSeek(const base::TimeDelta& seek_request, |
313 bool is_browser_seek) { | 363 bool is_browser_seek) { |
314 // Tell data factories to start next chunk with the new timestamp. | 364 // Tell data factories to start next chunk with the new timestamp. |
315 if (audio_factory_) | 365 if (audio_factory_) { |
| 366 base::TimeDelta time_to_seek = |
| 367 std::max(base::TimeDelta(), seek_request - audio_preroll_interval_); |
316 audio_factory_->SeekTo(time_to_seek); | 368 audio_factory_->SeekTo(time_to_seek); |
| 369 } |
317 if (video_factory_) { | 370 if (video_factory_) { |
| 371 base::TimeDelta time_to_seek = |
| 372 std::max(base::TimeDelta(), seek_request - video_preroll_interval_); |
318 video_factory_->SeekTo(time_to_seek); | 373 video_factory_->SeekTo(time_to_seek); |
319 video_factory_->RequestKeyFrame(); | 374 video_factory_->RequestKeyFrame(); |
320 } | 375 } |
321 | 376 |
322 ++num_seeks_; | 377 ++num_seeks_; |
323 if (is_browser_seek) | 378 if (is_browser_seek) |
324 ++num_browser_seeks_; | 379 ++num_browser_seeks_; |
325 | 380 |
326 // Post OnDemuxerSeekDone() to the player. | 381 // Post OnDemuxerSeekDone() to the player. |
327 DCHECK(client_); | 382 DCHECK(client_); |
328 base::TimeDelta reported_seek_time = | 383 base::TimeDelta reported_seek_time = |
329 is_browser_seek ? time_to_seek : kNoTimestamp(); | 384 is_browser_seek ? seek_request : kNoTimestamp(); |
330 GetMediaTaskRunner()->PostDelayedTask( | 385 GetMediaTaskRunner()->PostDelayedTask( |
331 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone, | 386 FROM_HERE, base::Bind(&DemuxerAndroidClient::OnDemuxerSeekDone, |
332 base::Unretained(client_), reported_seek_time), | 387 base::Unretained(client_), reported_seek_time), |
333 seek_done_delay_); | 388 seek_done_delay_); |
334 } | 389 } |
335 | 390 |
336 void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) { | 391 void MockDemuxerAndroid::PostConfigs(const DemuxerConfigs& configs) { |
337 RUN_ON_MEDIA_THREAD(MockDemuxerAndroid, PostConfigs, configs); | 392 RUN_ON_MEDIA_THREAD(MockDemuxerAndroid, PostConfigs, configs); |
338 | 393 |
339 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; | 394 DVLOG(1) << "MockDemuxerAndroid::" << __FUNCTION__; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 // reaches the given value or for timeout to expire. Returns true if the | 446 // reaches the given value or for timeout to expire. Returns true if the |
392 // playback has passed the given position. | 447 // playback has passed the given position. |
393 bool WaitForPlaybackBeyondPosition( | 448 bool WaitForPlaybackBeyondPosition( |
394 const base::TimeDelta& pts, | 449 const base::TimeDelta& pts, |
395 const base::TimeDelta& timeout = kDefaultTimeout); | 450 const base::TimeDelta& timeout = kDefaultTimeout); |
396 | 451 |
397 // Helper method that starts video only stream. Waits till it actually | 452 // Helper method that starts video only stream. Waits till it actually |
398 // started. | 453 // started. |
399 void StartVideoPlayback(base::TimeDelta duration); | 454 void StartVideoPlayback(base::TimeDelta duration); |
400 | 455 |
| 456 // Helper method that starts audio and video streams with preroll. |
| 457 // The preroll is achieved by setting significant video preroll interval |
| 458 // so video will have to catch up with audio. To make room for this interval |
| 459 // the Start() command is preceded by SeekTo(). |
| 460 void StartAVSeekAndPreroll(base::TimeDelta duration, |
| 461 base::TimeDelta seek_position, |
| 462 base::TimeDelta video_preroll); |
| 463 |
401 base::MessageLoop message_loop_; | 464 base::MessageLoop message_loop_; |
402 MockMediaPlayerManager manager_; | 465 MockMediaPlayerManager manager_; |
403 MockDemuxerAndroid* demuxer_; // owned by player_ | 466 MockDemuxerAndroid* demuxer_; // owned by player_ |
404 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; | 467 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; |
405 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; | 468 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; |
406 MediaCodecPlayer* player_; // raw pointer due to DeleteOnCorrectThread() | 469 MediaCodecPlayer* player_; // raw pointer due to DeleteOnCorrectThread() |
407 | 470 |
408 private: | 471 private: |
409 bool is_timeout_expired() const { return is_timeout_expired_; } | 472 bool is_timeout_expired() const { return is_timeout_expired_; } |
410 void SetTimeoutExpired(bool value) { is_timeout_expired_ = value; } | 473 void SetTimeoutExpired(bool value) { is_timeout_expired_ = value; } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 EXPECT_FALSE(manager_.IsPlaybackStarted()); | 576 EXPECT_FALSE(manager_.IsPlaybackStarted()); |
514 player_->Start(); | 577 player_->Start(); |
515 | 578 |
516 // Wait for playback to start. | 579 // Wait for playback to start. |
517 EXPECT_TRUE( | 580 EXPECT_TRUE( |
518 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, | 581 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
519 base::Unretained(&manager_)), | 582 base::Unretained(&manager_)), |
520 start_timeout)); | 583 start_timeout)); |
521 } | 584 } |
522 | 585 |
| 586 void MediaCodecPlayerTest::StartAVSeekAndPreroll( |
| 587 base::TimeDelta duration, |
| 588 base::TimeDelta seek_position, |
| 589 base::TimeDelta video_preroll) { |
| 590 const base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
| 591 |
| 592 demuxer_->SetVideoPrerollInterval(video_preroll); |
| 593 |
| 594 demuxer_->SetAudioFactory( |
| 595 scoped_ptr<AudioFactory>(new AudioFactory(duration))); |
| 596 demuxer_->SetVideoFactory( |
| 597 scoped_ptr<VideoFactory>(new VideoFactory(duration))); |
| 598 |
| 599 CreatePlayer(); |
| 600 SetVideoSurface(); |
| 601 |
| 602 // Set special testing callback to receive PTS from decoders. |
| 603 player_->SetDecodersTimeCallbackForTests( |
| 604 base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate, |
| 605 base::Unretained(&manager_))); |
| 606 |
| 607 // Wait till the player is initialized on media thread. |
| 608 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized, |
| 609 base::Unretained(demuxer_)))); |
| 610 |
| 611 // Post configuration after the player has been initialized. |
| 612 demuxer_->PostInternalConfigs(); |
| 613 |
| 614 // Issue SeekTo(). |
| 615 player_->SeekTo(seek_position); |
| 616 |
| 617 // Start the playback. |
| 618 player_->Start(); |
| 619 |
| 620 // Wait till preroll starts. |
| 621 EXPECT_TRUE(WaitForCondition( |
| 622 base::Bind(&MediaCodecPlayer::IsPrerollingForTests, |
| 623 base::Unretained(player_), DemuxerStream::VIDEO), |
| 624 start_timeout)); |
| 625 } |
| 626 |
523 TEST_F(MediaCodecPlayerTest, SetAudioConfigsBeforePlayerCreation) { | 627 TEST_F(MediaCodecPlayerTest, SetAudioConfigsBeforePlayerCreation) { |
524 // Post configuration when there is no player yet. | 628 // Post configuration when there is no player yet. |
525 EXPECT_EQ(nullptr, player_); | 629 EXPECT_EQ(nullptr, player_); |
526 | 630 |
527 base::TimeDelta duration = base::TimeDelta::FromSeconds(10); | 631 base::TimeDelta duration = base::TimeDelta::FromSeconds(10); |
528 | 632 |
529 demuxer_->PostConfigs( | 633 demuxer_->PostConfigs( |
530 TestDataFactory::CreateAudioConfigs(kCodecAAC, duration)); | 634 TestDataFactory::CreateAudioConfigs(kCodecAAC, duration)); |
531 | 635 |
532 // Wait until the configuration gets to the media thread. | 636 // Wait until the configuration gets to the media thread. |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 reconfigure_timeout)); | 1155 reconfigure_timeout)); |
1052 | 1156 |
1053 // Timestamps should start at the new seek position | 1157 // Timestamps should start at the new seek position |
1054 EXPECT_LE(seek_position, manager_.pts_stat_.min()); | 1158 EXPECT_LE(seek_position, manager_.pts_stat_.min()); |
1055 | 1159 |
1056 // The player should have reported the seek completion to the manager. | 1160 // The player should have reported the seek completion to the manager. |
1057 EXPECT_TRUE(WaitForCondition(base::Bind( | 1161 EXPECT_TRUE(WaitForCondition(base::Bind( |
1058 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_)))); | 1162 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_)))); |
1059 } | 1163 } |
1060 | 1164 |
| 1165 TEST_F(MediaCodecPlayerTest, VideoPrerollAfterSeek) { |
| 1166 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1167 |
| 1168 // A simple test for preroll for video stream only. After the seek is done |
| 1169 // the data factory generates the frames with pts before the seek time, and |
| 1170 // they should not be rendered. We deduce which frame is rendered by looking |
| 1171 // at the reported time progress. |
| 1172 |
| 1173 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(600); |
| 1174 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(500); |
| 1175 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
| 1176 |
| 1177 // Tell demuxer to make the first frame 100ms earlier than the seek request. |
| 1178 demuxer_->SetVideoPrerollInterval(base::TimeDelta::FromMilliseconds(100)); |
| 1179 |
| 1180 demuxer_->SetVideoFactory( |
| 1181 scoped_ptr<VideoFactory>(new VideoFactory(duration))); |
| 1182 |
| 1183 CreatePlayer(); |
| 1184 SetVideoSurface(); |
| 1185 |
| 1186 // Wait till the player is initialized on media thread. |
| 1187 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized, |
| 1188 base::Unretained(demuxer_)))); |
| 1189 |
| 1190 // Post configuration after the player has been initialized. |
| 1191 demuxer_->PostInternalConfigs(); |
| 1192 |
| 1193 // Issue SeekTo(). |
| 1194 player_->SeekTo(seek_position); |
| 1195 |
| 1196 // Start the playback and make sure it is started. |
| 1197 player_->Start(); |
| 1198 |
| 1199 EXPECT_TRUE( |
| 1200 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
| 1201 base::Unretained(&manager_)), |
| 1202 start_timeout)); |
| 1203 |
| 1204 // Wait for completion. |
| 1205 EXPECT_TRUE( |
| 1206 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted, |
| 1207 base::Unretained(&manager_)))); |
| 1208 |
| 1209 // The first pts should be equal than seek position even if video frames |
| 1210 // started 100 ms eralier than the seek request. |
| 1211 EXPECT_EQ(seek_position, manager_.pts_stat_.min()); |
| 1212 |
| 1213 EXPECT_EQ(6, manager_.pts_stat_.num_values()); |
| 1214 } |
| 1215 |
| 1216 TEST_F(MediaCodecPlayerTest, AVPrerollAudioWaitsForVideo) { |
| 1217 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1218 |
| 1219 // Test that during prerolling neither audio nor video plays and that both |
| 1220 // resume simultaneously after preroll is finished. In other words, test |
| 1221 // that preroll works. |
| 1222 // We put the video into the long preroll and intercept the time when first |
| 1223 // rendering happens in each stream. The moment of rendering is approximated |
| 1224 // with a decoder PTS that is delivered by a test-only callback. |
| 1225 |
| 1226 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000); |
| 1227 |
| 1228 // Set significant preroll interval. 500 ms means 25 frames, at 10 ms |
| 1229 // per frame it would take 250 ms to preroll. |
| 1230 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000); |
| 1231 base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500); |
| 1232 base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000); |
| 1233 |
| 1234 StartAVSeekAndPreroll(duration, seek_position, preroll_intvl); |
| 1235 |
| 1236 // Wait till preroll finishes and the real playback starts. |
| 1237 EXPECT_TRUE( |
| 1238 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
| 1239 base::Unretained(&manager_)), |
| 1240 preroll_timeout)); |
| 1241 |
| 1242 // Ensure that the first audio and video pts are close to each other and are |
| 1243 // reported at the close moments in time. |
| 1244 |
| 1245 EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1246 EXPECT_TRUE(WaitForCondition( |
| 1247 base::Bind(&MockMediaPlayerManager::HasFirstFrame, |
| 1248 base::Unretained(&manager_), DemuxerStream::VIDEO))); |
| 1249 |
| 1250 EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO), |
| 1251 manager_.FirstFramePTS(DemuxerStream::VIDEO), 10)); |
| 1252 |
| 1253 EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO), |
| 1254 manager_.FirstFrameTime(DemuxerStream::VIDEO), 50)); |
| 1255 |
| 1256 // The playback should start at |seek_position| |
| 1257 EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1)); |
| 1258 } |
| 1259 |
| 1260 TEST_F(MediaCodecPlayerTest, AVPrerollReleaseAndRestart) { |
| 1261 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1262 |
| 1263 // Test that player will resume prerolling if prerolling is interrupted by |
| 1264 // Release() and Start(). |
| 1265 |
| 1266 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000); |
| 1267 |
| 1268 // Set significant preroll interval. 500 ms means 25 frames, at 10 ms |
| 1269 // per frame it would take 250 ms to preroll. |
| 1270 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000); |
| 1271 base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500); |
| 1272 |
| 1273 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
| 1274 base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000); |
| 1275 |
| 1276 StartAVSeekAndPreroll(duration, seek_position, preroll_intvl); |
| 1277 |
| 1278 // Issue Release(). |
| 1279 player_->Release(); |
| 1280 |
| 1281 // Make sure we have not been playing. |
| 1282 WaitForDelay(base::TimeDelta::FromMilliseconds(400)); |
| 1283 |
| 1284 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1285 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO)); |
| 1286 |
| 1287 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO)); |
| 1288 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO)); |
| 1289 EXPECT_EQ(0, manager_.pts_stat_.num_values()); |
| 1290 |
| 1291 // Restart. Release() removed the video surface, we need to set it again. |
| 1292 SetVideoSurface(); |
| 1293 player_->Start(); |
| 1294 |
| 1295 // The playback should pass through prerolling phase. |
| 1296 EXPECT_TRUE(WaitForCondition( |
| 1297 base::Bind(&MediaCodecPlayer::IsPrerollingForTests, |
| 1298 base::Unretained(player_), DemuxerStream::VIDEO), |
| 1299 start_timeout)); |
| 1300 |
| 1301 // Wait till preroll finishes and the real playback starts. |
| 1302 EXPECT_TRUE( |
| 1303 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
| 1304 base::Unretained(&manager_)), |
| 1305 preroll_timeout)); |
| 1306 |
| 1307 // Ensure that the first audio and video pts are close to each other and are |
| 1308 // reported at the close moments in time. |
| 1309 |
| 1310 EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1311 EXPECT_TRUE(WaitForCondition( |
| 1312 base::Bind(&MockMediaPlayerManager::HasFirstFrame, |
| 1313 base::Unretained(&manager_), DemuxerStream::VIDEO))); |
| 1314 |
| 1315 EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO), |
| 1316 manager_.FirstFramePTS(DemuxerStream::VIDEO), 10)); |
| 1317 |
| 1318 EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO), |
| 1319 manager_.FirstFrameTime(DemuxerStream::VIDEO), 50)); |
| 1320 |
| 1321 // The playback should start at |seek_position| |
| 1322 EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1)); |
| 1323 } |
| 1324 |
| 1325 TEST_F(MediaCodecPlayerTest, AVPrerollStopAndRestart) { |
| 1326 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1327 |
| 1328 // Test that if Pause() happens during the preroll phase, |
| 1329 // we continue to do preroll after restart. |
| 1330 |
| 1331 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1200); |
| 1332 |
| 1333 // Set significant preroll interval. 500 ms means 25 frames, at 10 ms |
| 1334 // per frame it would take 250 ms to preroll. |
| 1335 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000); |
| 1336 base::TimeDelta preroll_intvl = base::TimeDelta::FromMilliseconds(500); |
| 1337 |
| 1338 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
| 1339 base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(1000); |
| 1340 |
| 1341 StartAVSeekAndPreroll(duration, seek_position, preroll_intvl); |
| 1342 |
| 1343 // Video stream should be prerolling. Request to stop. |
| 1344 EXPECT_FALSE(IsPaused()); |
| 1345 player_->Pause(true); |
| 1346 |
| 1347 EXPECT_TRUE(WaitForCondition( |
| 1348 base::Bind(&MediaCodecPlayerTest::IsPaused, base::Unretained(this)))); |
| 1349 |
| 1350 // Test that we have not been playing. |
| 1351 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1352 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO)); |
| 1353 |
| 1354 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO)); |
| 1355 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO)); |
| 1356 EXPECT_EQ(0, manager_.pts_stat_.num_values()); |
| 1357 |
| 1358 // Restart. |
| 1359 player_->Start(); |
| 1360 |
| 1361 // There should be preroll after the start. |
| 1362 EXPECT_TRUE(WaitForCondition( |
| 1363 base::Bind(&MediaCodecPlayer::IsPrerollingForTests, |
| 1364 base::Unretained(player_), DemuxerStream::VIDEO), |
| 1365 start_timeout)); |
| 1366 |
| 1367 // Wait for a short period of time, so that preroll is still ongoing, |
| 1368 // and pause again. |
| 1369 WaitForDelay(base::TimeDelta::FromMilliseconds(100)); |
| 1370 |
| 1371 EXPECT_FALSE(IsPaused()); |
| 1372 player_->Pause(true); |
| 1373 |
| 1374 EXPECT_TRUE(WaitForCondition( |
| 1375 base::Bind(&MediaCodecPlayerTest::IsPaused, base::Unretained(this)))); |
| 1376 |
| 1377 // Check that we still haven't started rendering. |
| 1378 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1379 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO)); |
| 1380 |
| 1381 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO)); |
| 1382 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO)); |
| 1383 EXPECT_EQ(0, manager_.pts_stat_.num_values()); |
| 1384 |
| 1385 // Restart again. |
| 1386 player_->Start(); |
| 1387 |
| 1388 // Wait till we start to play. |
| 1389 EXPECT_TRUE( |
| 1390 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
| 1391 base::Unretained(&manager_)), |
| 1392 preroll_timeout)); |
| 1393 |
| 1394 // Check that we did prerolling, i.e. audio did wait for video. |
| 1395 EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1396 EXPECT_TRUE(WaitForCondition( |
| 1397 base::Bind(&MockMediaPlayerManager::HasFirstFrame, |
| 1398 base::Unretained(&manager_), DemuxerStream::VIDEO))); |
| 1399 |
| 1400 EXPECT_TRUE(AlmostEqual(manager_.FirstFramePTS(DemuxerStream::AUDIO), |
| 1401 manager_.FirstFramePTS(DemuxerStream::VIDEO), 10)); |
| 1402 |
| 1403 EXPECT_TRUE(AlmostEqual(manager_.FirstFrameTime(DemuxerStream::AUDIO), |
| 1404 manager_.FirstFrameTime(DemuxerStream::VIDEO), 50)); |
| 1405 |
| 1406 // The playback should start at |seek_position| |
| 1407 EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1)); |
| 1408 } |
| 1409 |
| 1410 TEST_F(MediaCodecPlayerTest, AVPrerollVideoEndsWhilePrerolling) { |
| 1411 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1412 |
| 1413 // Test that when one stream ends in the preroll phase and another is not |
| 1414 // the preroll finishes and playback continues after it. |
| 1415 |
| 1416 base::TimeDelta audio_duration = base::TimeDelta::FromMilliseconds(1100); |
| 1417 base::TimeDelta video_duration = base::TimeDelta::FromMilliseconds(900); |
| 1418 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(1000); |
| 1419 base::TimeDelta video_preroll_intvl = base::TimeDelta::FromMilliseconds(200); |
| 1420 |
| 1421 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(800); |
| 1422 base::TimeDelta preroll_timeout = base::TimeDelta::FromMilliseconds(400); |
| 1423 |
| 1424 demuxer_->SetVideoPrerollInterval(video_preroll_intvl); |
| 1425 |
| 1426 demuxer_->SetAudioFactory( |
| 1427 scoped_ptr<AudioFactory>(new AudioFactory(audio_duration))); |
| 1428 demuxer_->SetVideoFactory( |
| 1429 scoped_ptr<VideoFactory>(new VideoFactory(video_duration))); |
| 1430 |
| 1431 CreatePlayer(); |
| 1432 SetVideoSurface(); |
| 1433 |
| 1434 // Set special testing callback to receive PTS from decoders. |
| 1435 player_->SetDecodersTimeCallbackForTests( |
| 1436 base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate, |
| 1437 base::Unretained(&manager_))); |
| 1438 |
| 1439 // Wait till the player is initialized on media thread. |
| 1440 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized, |
| 1441 base::Unretained(demuxer_)))); |
| 1442 |
| 1443 // Post configuration after the player has been initialized. |
| 1444 demuxer_->PostInternalConfigs(); |
| 1445 |
| 1446 // Issue SeekTo(). |
| 1447 player_->SeekTo(seek_position); |
| 1448 |
| 1449 // Start the playback. |
| 1450 player_->Start(); |
| 1451 |
| 1452 // The video decoder should start prerolling |
| 1453 // Wait till preroll starts. |
| 1454 EXPECT_TRUE(WaitForCondition( |
| 1455 base::Bind(&MediaCodecPlayer::IsPrerollingForTests, |
| 1456 base::Unretained(player_), DemuxerStream::VIDEO), |
| 1457 start_timeout)); |
| 1458 |
| 1459 // Wait for playback to start. |
| 1460 EXPECT_TRUE( |
| 1461 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, |
| 1462 base::Unretained(&manager_)), |
| 1463 preroll_timeout)); |
| 1464 |
| 1465 EXPECT_TRUE(manager_.HasFirstFrame(DemuxerStream::AUDIO)); |
| 1466 |
| 1467 // Play till completion. |
| 1468 EXPECT_TRUE( |
| 1469 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted, |
| 1470 base::Unretained(&manager_)))); |
| 1471 |
| 1472 // There should not be any video frames. |
| 1473 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO)); |
| 1474 } |
| 1475 |
1061 } // namespace media | 1476 } // namespace media |
OLD | NEW |