| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 // TODO(wolenetz/qinmin): Simplify tests with more effective mock usage, and | 34 // TODO(wolenetz/qinmin): Simplify tests with more effective mock usage, and |
| 35 // fix flaky pointer-based MDJ inequality testing. See http://crbug.com/327839. | 35 // fix flaky pointer-based MDJ inequality testing. See http://crbug.com/327839. |
| 36 | 36 |
| 37 // Mock of MediaPlayerManager for testing purpose. | 37 // Mock of MediaPlayerManager for testing purpose. |
| 38 class MockMediaPlayerManager : public MediaPlayerManager { | 38 class MockMediaPlayerManager : public MediaPlayerManager { |
| 39 public: | 39 public: |
| 40 explicit MockMediaPlayerManager(base::MessageLoop* message_loop) | 40 explicit MockMediaPlayerManager(base::MessageLoop* message_loop) |
| 41 : message_loop_(message_loop), | 41 : message_loop_(message_loop), |
| 42 playback_completed_(false), | 42 playback_completed_(false), |
| 43 num_resources_requested_(0), | 43 num_resources_requested_(0), |
| 44 num_resources_released_(0) {} | 44 num_resources_released_(0), |
| 45 timestamp_updated_(false) {} |
| 45 virtual ~MockMediaPlayerManager() {} | 46 virtual ~MockMediaPlayerManager() {} |
| 46 | 47 |
| 47 // MediaPlayerManager implementation. | 48 // MediaPlayerManager implementation. |
| 48 virtual MediaResourceGetter* GetMediaResourceGetter() OVERRIDE { | 49 virtual MediaResourceGetter* GetMediaResourceGetter() OVERRIDE { |
| 49 return NULL; | 50 return NULL; |
| 50 } | 51 } |
| 51 virtual void OnTimeUpdate(int player_id, | 52 virtual void OnTimeUpdate(int player_id, |
| 52 base::TimeDelta current_time) OVERRIDE {} | 53 base::TimeDelta current_time) OVERRIDE { |
| 54 timestamp_updated_ = true; |
| 55 } |
| 53 virtual void OnMediaMetadataChanged( | 56 virtual void OnMediaMetadataChanged( |
| 54 int player_id, base::TimeDelta duration, int width, int height, | 57 int player_id, base::TimeDelta duration, int width, int height, |
| 55 bool success) OVERRIDE {} | 58 bool success) OVERRIDE {} |
| 56 virtual void OnPlaybackComplete(int player_id) OVERRIDE { | 59 virtual void OnPlaybackComplete(int player_id) OVERRIDE { |
| 57 playback_completed_ = true; | 60 playback_completed_ = true; |
| 58 if (message_loop_->is_running()) | 61 if (message_loop_->is_running()) |
| 59 message_loop_->Quit(); | 62 message_loop_->Quit(); |
| 60 } | 63 } |
| 61 virtual void OnMediaInterrupted(int player_id) OVERRIDE {} | 64 virtual void OnMediaInterrupted(int player_id) OVERRIDE {} |
| 62 virtual void OnBufferingUpdate(int player_id, int percentage) OVERRIDE {} | 65 virtual void OnBufferingUpdate(int player_id, int percentage) OVERRIDE {} |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 } | 100 } |
| 98 | 101 |
| 99 void OnMediaResourcesRequested(int player_id) { | 102 void OnMediaResourcesRequested(int player_id) { |
| 100 num_resources_requested_++; | 103 num_resources_requested_++; |
| 101 } | 104 } |
| 102 | 105 |
| 103 void OnMediaResourcesReleased(int player_id) { | 106 void OnMediaResourcesReleased(int player_id) { |
| 104 num_resources_released_++; | 107 num_resources_released_++; |
| 105 } | 108 } |
| 106 | 109 |
| 110 bool timestamp_updated() const { |
| 111 return timestamp_updated_; |
| 112 } |
| 113 |
| 114 void ResetTimestampUpdated() { |
| 115 timestamp_updated_ = false; |
| 116 } |
| 117 |
| 107 private: | 118 private: |
| 108 base::MessageLoop* message_loop_; | 119 base::MessageLoop* message_loop_; |
| 109 bool playback_completed_; | 120 bool playback_completed_; |
| 110 // The number of resource requests this object has seen. | 121 // The number of resource requests this object has seen. |
| 111 int num_resources_requested_; | 122 int num_resources_requested_; |
| 112 // The number of released resources. | 123 // The number of released resources. |
| 113 int num_resources_released_; | 124 int num_resources_released_; |
| 125 // Playback timestamp was updated. |
| 126 bool timestamp_updated_; |
| 114 | 127 |
| 115 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); | 128 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); |
| 116 }; | 129 }; |
| 117 | 130 |
| 118 class MockDemuxerAndroid : public DemuxerAndroid { | 131 class MockDemuxerAndroid : public DemuxerAndroid { |
| 119 public: | 132 public: |
| 120 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) | 133 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) |
| 121 : message_loop_(message_loop), | 134 : message_loop_(message_loop), |
| 122 num_data_requests_(0), | 135 num_data_requests_(0), |
| 123 num_seek_requests_(0), | 136 num_seek_requests_(0), |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 demuxer_->num_data_requests()); | 345 demuxer_->num_data_requests()); |
| 333 | 346 |
| 334 // Verify player has decoder job iff the config included the media type for | 347 // Verify player has decoder job iff the config included the media type for |
| 335 // the job and the player is expected to request data due to Start(), above. | 348 // the job and the player is expected to request data due to Start(), above. |
| 336 EXPECT_EQ(expect_player_requests_data && has_audio, | 349 EXPECT_EQ(expect_player_requests_data && has_audio, |
| 337 GetMediaDecoderJob(true) != NULL); | 350 GetMediaDecoderJob(true) != NULL); |
| 338 EXPECT_EQ(expect_player_requests_data && has_video, | 351 EXPECT_EQ(expect_player_requests_data && has_video, |
| 339 GetMediaDecoderJob(false) != NULL); | 352 GetMediaDecoderJob(false) != NULL); |
| 340 } | 353 } |
| 341 | 354 |
| 355 // Keeps decoding audio data until the decoder starts to output samples. |
| 356 // Gives up if no audio output after decoding 10 frames. |
| 357 void DecodeAudioDataUntilOutputBecomesAvailable() { |
| 358 EXPECT_TRUE(player_.IsPlaying()); |
| 359 base::TimeDelta current_time = player_.GetCurrentTime(); |
| 360 base::TimeDelta start_timestamp = current_time; |
| 361 for (int i = 0; i < 10; ++i) { |
| 362 manager_.ResetTimestampUpdated(); |
| 363 player_.OnDemuxerDataAvailable( |
| 364 CreateReadFromDemuxerAckForAudio(i > 3 ? 3 : i)); |
| 365 WaitForAudioDecodeDone(); |
| 366 base::TimeDelta new_current_time = player_.GetCurrentTime(); |
| 367 EXPECT_LE(current_time.InMilliseconds(), |
| 368 new_current_time.InMilliseconds()); |
| 369 current_time = new_current_time; |
| 370 if (manager_.timestamp_updated()) { |
| 371 EXPECT_LT(start_timestamp.InMillisecondsF(), |
| 372 new_current_time.InMillisecondsF()); |
| 373 return; |
| 374 } |
| 375 } |
| 376 EXPECT_TRUE(false); |
| 377 } |
| 378 |
| 342 AccessUnit CreateAccessUnitWithData(bool is_audio, int audio_packet_id) { | 379 AccessUnit CreateAccessUnitWithData(bool is_audio, int audio_packet_id) { |
| 343 AccessUnit unit; | 380 AccessUnit unit; |
| 344 | 381 |
| 345 unit.status = DemuxerStream::kOk; | 382 unit.status = DemuxerStream::kOk; |
| 346 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile( | 383 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile( |
| 347 is_audio ? base::StringPrintf("vorbis-packet-%d", audio_packet_id) | 384 is_audio ? base::StringPrintf("vorbis-packet-%d", audio_packet_id) |
| 348 : "vp8-I-frame-320x240"); | 385 : "vp8-I-frame-320x240"); |
| 349 unit.data = std::vector<uint8>( | 386 unit.data = std::vector<uint8>( |
| 350 buffer->data(), buffer->data() + buffer->data_size()); | 387 buffer->data(), buffer->data() + buffer->data_size()); |
| 351 | 388 |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 // No seeks should have occurred. | 1107 // No seeks should have occurred. |
| 1071 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1108 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 1072 } | 1109 } |
| 1073 | 1110 |
| 1074 TEST_F(MediaSourcePlayerTest, StartTimeTicksResetAfterDecoderUnderruns) { | 1111 TEST_F(MediaSourcePlayerTest, StartTimeTicksResetAfterDecoderUnderruns) { |
| 1075 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1112 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1076 | 1113 |
| 1077 // Test start time ticks will reset after decoder job underruns. | 1114 // Test start time ticks will reset after decoder job underruns. |
| 1078 StartAudioDecoderJob(true); | 1115 StartAudioDecoderJob(true); |
| 1079 | 1116 |
| 1080 // For the first couple chunks, the decoder job may return | 1117 DecodeAudioDataUntilOutputBecomesAvailable(); |
| 1081 // DECODE_FORMAT_CHANGED status instead of DECODE_SUCCEEDED status. Decode | |
| 1082 // more frames to guarantee that DECODE_SUCCEEDED will be returned. | |
| 1083 for (int i = 0; i < 4; ++i) { | |
| 1084 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(i)); | |
| 1085 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1086 // Decode data until decoder started requesting new data again. | |
| 1087 WaitForAudioDecodeDone(); | |
| 1088 } | |
| 1089 | 1118 |
| 1090 // The decoder job should finish and a new request will be sent. | 1119 // The decoder job should finish and a new request will be sent. |
| 1091 EXPECT_EQ(5, demuxer_->num_data_requests()); | |
| 1092 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1093 base::TimeTicks previous = StartTimeTicks(); | 1120 base::TimeTicks previous = StartTimeTicks(); |
| 1121 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); |
| 1094 | 1122 |
| 1095 // Let the decoder starve. | 1123 // Let the decoder starve. |
| 1096 TriggerPlayerStarvation(); | 1124 TriggerPlayerStarvation(); |
| 1097 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); | |
| 1098 WaitForAudioDecodeDone(); | 1125 WaitForAudioDecodeDone(); |
| 1099 | 1126 |
| 1100 // Verify the start time ticks is cleared at this point because the | 1127 // Verify the start time ticks is cleared at this point because the |
| 1101 // player is prefetching. | 1128 // player is prefetching. |
| 1102 EXPECT_TRUE(StartTimeTicks() == base::TimeTicks()); | 1129 EXPECT_TRUE(StartTimeTicks() == base::TimeTicks()); |
| 1103 | 1130 |
| 1104 // Send new data to the decoder so it can finish prefetching. This should | 1131 // Send new data to the decoder so it can finish prefetching. This should |
| 1105 // reset the start time ticks. | 1132 // reset the start time ticks. |
| 1106 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); | 1133 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); |
| 1107 EXPECT_TRUE(StartTimeTicks() != base::TimeTicks()); | 1134 EXPECT_TRUE(StartTimeTicks() != base::TimeTicks()); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 TEST_F(MediaSourcePlayerTest, SeekingAfterCompletingPrerollRestartsPreroll) { | 1492 TEST_F(MediaSourcePlayerTest, SeekingAfterCompletingPrerollRestartsPreroll) { |
| 1466 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1493 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1467 | 1494 |
| 1468 // Test decoder job will begin prerolling upon seek, when it was not | 1495 // Test decoder job will begin prerolling upon seek, when it was not |
| 1469 // prerolling prior to the seek. | 1496 // prerolling prior to the seek. |
| 1470 StartAudioDecoderJob(true); | 1497 StartAudioDecoderJob(true); |
| 1471 MediaDecoderJob* decoder_job = GetMediaDecoderJob(true); | 1498 MediaDecoderJob* decoder_job = GetMediaDecoderJob(true); |
| 1472 EXPECT_TRUE(IsPrerolling(true)); | 1499 EXPECT_TRUE(IsPrerolling(true)); |
| 1473 | 1500 |
| 1474 // Complete the initial preroll by feeding data to the decoder. | 1501 // Complete the initial preroll by feeding data to the decoder. |
| 1475 for (int i = 0; i < 4; ++i) { | 1502 DecodeAudioDataUntilOutputBecomesAvailable(); |
| 1476 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(i)); | |
| 1477 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1478 WaitForAudioDecodeDone(); | |
| 1479 } | |
| 1480 EXPECT_LT(0.0, player_.GetCurrentTime().InMillisecondsF()); | |
| 1481 EXPECT_FALSE(IsPrerolling(true)); | 1503 EXPECT_FALSE(IsPrerolling(true)); |
| 1482 | 1504 |
| 1483 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(500)); | 1505 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(500)); |
| 1484 | 1506 |
| 1485 // Prerolling should have begun again. | 1507 // Prerolling should have begun again. |
| 1486 EXPECT_TRUE(IsPrerolling(true)); | 1508 EXPECT_TRUE(IsPrerolling(true)); |
| 1487 EXPECT_EQ(500.0, GetPrerollTimestamp().InMillisecondsF()); | 1509 EXPECT_EQ(500.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1488 | 1510 |
| 1489 // Send data at and after the seek position. Prerolling should complete. | 1511 // Send data at and after the seek position. Prerolling should complete. |
| 1490 for (int i = 0; i < 4; ++i) { | 1512 for (int i = 0; i < 4; ++i) { |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2060 // player has not yet received media crypto. | 2082 // player has not yet received media crypto. |
| 2061 DemuxerConfigs configs = CreateVideoDemuxerConfigs(); | 2083 DemuxerConfigs configs = CreateVideoDemuxerConfigs(); |
| 2062 configs.is_video_encrypted = true; | 2084 configs.is_video_encrypted = true; |
| 2063 | 2085 |
| 2064 player_.OnDemuxerConfigsAvailable(configs); | 2086 player_.OnDemuxerConfigsAvailable(configs); |
| 2065 CreateNextTextureAndSetVideoSurface(); | 2087 CreateNextTextureAndSetVideoSurface(); |
| 2066 EXPECT_FALSE(IsPendingSurfaceChange()); | 2088 EXPECT_FALSE(IsPendingSurfaceChange()); |
| 2067 EXPECT_FALSE(GetMediaDecoderJob(false)); | 2089 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 2068 } | 2090 } |
| 2069 | 2091 |
| 2092 TEST_F(MediaSourcePlayerTest, CurrentTimeUpdatedWhileDecoderStarved) { |
| 2093 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 2094 |
| 2095 // Test that current time is updated while decoder is starved. |
| 2096 StartAudioDecoderJob(true); |
| 2097 DecodeAudioDataUntilOutputBecomesAvailable(); |
| 2098 |
| 2099 // Trigger starvation while the decoder is decoding. |
| 2100 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); |
| 2101 manager_.ResetTimestampUpdated(); |
| 2102 TriggerPlayerStarvation(); |
| 2103 WaitForAudioDecodeDone(); |
| 2104 |
| 2105 // Current time should be updated. |
| 2106 EXPECT_TRUE(manager_.timestamp_updated()); |
| 2107 } |
| 2108 |
| 2109 TEST_F(MediaSourcePlayerTest, CurrentTimeKeepsIncreasingAfterConfigChange) { |
| 2110 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 2111 |
| 2112 // Test current time keep on increasing after audio config change. |
| 2113 // Test that current time is updated while decoder is starved. |
| 2114 StartAudioDecoderJob(true); |
| 2115 |
| 2116 DecodeAudioDataUntilOutputBecomesAvailable(); |
| 2117 |
| 2118 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged(true, 0); |
| 2119 player_.OnDemuxerDataAvailable(data); |
| 2120 WaitForAudioDecodeDone(); |
| 2121 |
| 2122 // Simulate arrival of new configs. |
| 2123 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs(kCodecVorbis)); |
| 2124 DecodeAudioDataUntilOutputBecomesAvailable(); |
| 2125 } |
| 2126 |
| 2070 } // namespace media | 2127 } // namespace media |
| OLD | NEW |