Chromium Code Reviews| 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/callback_helpers.h" | |
| 8 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 10 #include "media/base/android/media_codec_bridge.h" | 11 #include "media/base/android/media_codec_bridge.h" |
| 11 #include "media/base/android/media_drm_bridge.h" | 12 #include "media/base/android/media_drm_bridge.h" |
| 12 #include "media/base/android/media_player_manager.h" | 13 #include "media/base/android/media_player_manager.h" |
| 13 #include "media/base/android/media_source_player.h" | 14 #include "media/base/android/media_source_player.h" |
| 15 #include "media/base/bind_to_loop.h" | |
| 14 #include "media/base/decoder_buffer.h" | 16 #include "media/base/decoder_buffer.h" |
| 15 #include "media/base/test_data_util.h" | 17 #include "media/base/test_data_util.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "ui/gl/android/surface_texture.h" | 19 #include "ui/gl/android/surface_texture.h" |
| 18 | 20 |
| 19 namespace media { | 21 namespace media { |
| 20 | 22 |
| 21 // Helper macro to skip the test if MediaCodecBridge isn't available. | 23 // Helper macro to skip the test if MediaCodecBridge isn't available. |
| 22 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ | 24 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ |
| 23 do { \ | 25 do { \ |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 virtual void OnKeyAdded(int key_id, | 75 virtual void OnKeyAdded(int key_id, |
| 74 const std::string& session_id) OVERRIDE {} | 76 const std::string& session_id) OVERRIDE {} |
| 75 virtual void OnKeyError(int key_id, | 77 virtual void OnKeyError(int key_id, |
| 76 const std::string& session_id, | 78 const std::string& session_id, |
| 77 MediaKeys::KeyError error_code, | 79 MediaKeys::KeyError error_code, |
| 78 int system_code) OVERRIDE {} | 80 int system_code) OVERRIDE {} |
| 79 virtual void OnKeyMessage(int key_id, | 81 virtual void OnKeyMessage(int key_id, |
| 80 const std::string& session_id, | 82 const std::string& session_id, |
| 81 const std::vector<uint8>& message, | 83 const std::vector<uint8>& message, |
| 82 const std::string& destination_url) OVERRIDE {} | 84 const std::string& destination_url) OVERRIDE {} |
| 85 virtual void OnMediaDecoderCallbackForTesting() OVERRIDE { | |
|
acolwell GONE FROM CHROMIUM
2013/10/30 23:29:53
This should be in MSP not here.
wolenetz
2013/10/31 01:39:11
Done.
| |
| 86 if (media_decoder_test_cb_.is_null()) | |
| 87 return; | |
| 88 base::ResetAndReturn(&media_decoder_test_cb_).Run(); | |
| 89 } | |
| 90 | |
| 91 // Hook the next OnMediaDecoderCallbackForTesting() to run |decode_cb|. | |
| 92 void HookNextMediaDecoderCallback(const base::Closure& decode_cb) { | |
| 93 media_decoder_test_cb_ = decode_cb; | |
| 94 } | |
| 83 | 95 |
| 84 private: | 96 private: |
| 85 base::MessageLoop* message_loop_; | 97 base::MessageLoop* message_loop_; |
| 98 base::Closure media_decoder_test_cb_; | |
| 86 | 99 |
| 87 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); | 100 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); |
| 88 }; | 101 }; |
| 89 | 102 |
| 90 class MockDemuxerAndroid : public DemuxerAndroid { | 103 class MockDemuxerAndroid : public DemuxerAndroid { |
| 91 public: | 104 public: |
| 92 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) | 105 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) |
| 93 : message_loop_(message_loop), | 106 : message_loop_(message_loop), |
| 94 num_data_requests_(0), | 107 num_data_requests_(0), |
| 95 num_seek_requests_(0), | 108 num_seek_requests_(0), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 148 |
| 136 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); | 149 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); |
| 137 }; | 150 }; |
| 138 | 151 |
| 139 class MediaSourcePlayerTest : public testing::Test { | 152 class MediaSourcePlayerTest : public testing::Test { |
| 140 public: | 153 public: |
| 141 MediaSourcePlayerTest() | 154 MediaSourcePlayerTest() |
| 142 : manager_(&message_loop_), | 155 : manager_(&message_loop_), |
| 143 demuxer_(new MockDemuxerAndroid(&message_loop_)), | 156 demuxer_(new MockDemuxerAndroid(&message_loop_)), |
| 144 player_(0, &manager_, scoped_ptr<DemuxerAndroid>(demuxer_)), | 157 player_(0, &manager_, scoped_ptr<DemuxerAndroid>(demuxer_)), |
| 158 decoder_callback_hook_executed_(false), | |
| 145 surface_texture_a_is_next_(true) {} | 159 surface_texture_a_is_next_(true) {} |
| 146 virtual ~MediaSourcePlayerTest() {} | 160 virtual ~MediaSourcePlayerTest() {} |
| 147 | 161 |
| 148 protected: | 162 protected: |
| 149 // Get the decoder job from the MediaSourcePlayer. | 163 // Get the decoder job from the MediaSourcePlayer. |
| 150 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { | 164 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { |
| 151 if (is_audio) { | 165 if (is_audio) { |
| 152 return reinterpret_cast<MediaDecoderJob*>( | 166 return reinterpret_cast<MediaDecoderJob*>( |
| 153 player_.audio_decoder_job_.get()); | 167 player_.audio_decoder_job_.get()); |
| 154 } | 168 } |
| 155 return reinterpret_cast<MediaDecoderJob*>( | 169 return reinterpret_cast<MediaDecoderJob*>( |
| 156 player_.video_decoder_job_.get()); | 170 player_.video_decoder_job_.get()); |
| 157 } | 171 } |
| 158 | 172 |
| 159 // Get the per-job prerolling status from the MediaSourcePlayer's job matching | 173 // Get the per-job prerolling status from the MediaSourcePlayer's job matching |
| 160 // |is_audio|. Caller must guard against NPE if the player's job is NULL. | 174 // |is_audio|. Caller must guard against NPE if the player's job is NULL. |
| 161 bool IsPrerolling(bool is_audio) { | 175 bool IsPrerolling(bool is_audio) { |
| 162 return GetMediaDecoderJob(is_audio)->prerolling(); | 176 return GetMediaDecoderJob(is_audio)->prerolling(); |
| 163 } | 177 } |
| 164 | 178 |
| 165 // Get the preroll timestamp from the MediaSourcePlayer. | 179 // Get the preroll timestamp from the MediaSourcePlayer. |
| 166 base::TimeDelta GetPrerollTimestamp() { | 180 base::TimeDelta GetPrerollTimestamp() { |
| 167 return player_.preroll_timestamp_; | 181 return player_.preroll_timestamp_; |
| 168 } | 182 } |
| 169 | 183 |
| 184 // Check if the player is pending a prefetch done event. | |
| 185 bool IsPendingPrefetchDone() { | |
| 186 return player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING); | |
| 187 } | |
| 188 | |
| 189 // Check if the player is pending a config change event. | |
| 190 bool IsPendingConfigChange() { | |
| 191 return player_.IsEventPending(player_.CONFIG_CHANGE_EVENT_PENDING); | |
| 192 } | |
| 193 | |
| 194 // Check if the player is pending a seek event. | |
| 195 bool IsPendingSeek() { | |
| 196 return player_.IsEventPending(player_.SEEK_EVENT_PENDING); | |
| 197 } | |
| 198 | |
| 199 // Check if the player is pending a surface change event. | |
| 200 bool IsPendingSurfaceChange() { | |
| 201 return player_.IsEventPending(player_.SURFACE_CHANGE_EVENT_PENDING); | |
| 202 } | |
| 203 | |
| 204 // Check if the player is pending a prefetch request event. | |
| 205 bool IsPendingPrefetchRequest() { | |
| 206 return player_.IsEventPending(player_.PREFETCH_REQUEST_EVENT_PENDING); | |
| 207 } | |
| 208 | |
| 209 // Simulate player has reached starvation timeout. | |
| 210 void TriggerPlayerStarvation() { | |
| 211 player_.decoder_starvation_callback_.Cancel(); | |
| 212 player_.OnDecoderStarved(); | |
| 213 } | |
| 214 | |
| 215 // Asynch test callback posted upon decode completion to verify that a pending | |
| 216 // prefetch done event is cleared across |player_|'s Release(). This helps | |
| 217 // ensure the ReleaseWithOnPrefetchDoneAlreadyPosted test scenario is met. | |
| 218 void ReleaseWithPendingPrefetchDoneVerification() { | |
| 219 EXPECT_TRUE(player_.IsPlaying()); | |
| 220 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 221 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 222 player_.Release(); | |
| 223 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 224 EXPECT_FALSE(player_.IsPlaying()); | |
| 225 EXPECT_FALSE(decoder_callback_hook_executed_); | |
| 226 decoder_callback_hook_executed_ = true; | |
| 227 } | |
| 228 | |
| 170 DemuxerConfigs CreateAudioDemuxerConfigs() { | 229 DemuxerConfigs CreateAudioDemuxerConfigs() { |
| 171 DemuxerConfigs configs; | 230 DemuxerConfigs configs; |
| 172 configs.audio_codec = kCodecVorbis; | 231 configs.audio_codec = kCodecVorbis; |
| 173 configs.audio_channels = 2; | 232 configs.audio_channels = 2; |
| 174 configs.audio_sampling_rate = 44100; | 233 configs.audio_sampling_rate = 44100; |
| 175 configs.is_audio_encrypted = false; | 234 configs.is_audio_encrypted = false; |
| 176 configs.duration_ms = kDefaultDurationInMs; | 235 configs.duration_ms = kDefaultDurationInMs; |
| 177 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); | 236 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); |
| 178 configs.audio_extra_data = std::vector<uint8>( | 237 configs.audio_extra_data = std::vector<uint8>( |
| 179 buffer->data(), | 238 buffer->data(), |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 } | 520 } |
| 462 | 521 |
| 463 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, | 522 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, |
| 464 const std::string& security_level, | 523 const std::string& security_level, |
| 465 const std::string& container, | 524 const std::string& container, |
| 466 const std::vector<std::string>& codecs) { | 525 const std::vector<std::string>& codecs) { |
| 467 return MediaSourcePlayer::IsTypeSupported( | 526 return MediaSourcePlayer::IsTypeSupported( |
| 468 scheme_uuid, security_level, container, codecs); | 527 scheme_uuid, security_level, container, codecs); |
| 469 } | 528 } |
| 470 | 529 |
| 471 protected: | |
| 472 base::MessageLoop message_loop_; | 530 base::MessageLoop message_loop_; |
| 473 MockMediaPlayerManager manager_; | 531 MockMediaPlayerManager manager_; |
| 474 MockDemuxerAndroid* demuxer_; // Owned by |player_|. | 532 MockDemuxerAndroid* demuxer_; // Owned by |player_|. |
| 475 MediaSourcePlayer player_; | 533 MediaSourcePlayer player_; |
| 476 | 534 |
| 535 // Track whether a possibly asynch decoder callback test hook has run. | |
| 536 bool decoder_callback_hook_executed_; | |
| 537 | |
| 477 // We need to keep the surface texture while the decoder is actively decoding. | 538 // We need to keep the surface texture while the decoder is actively decoding. |
| 478 // Otherwise, it may trigger unexpected crashes on some devices. To switch | 539 // Otherwise, it may trigger unexpected crashes on some devices. To switch |
| 479 // surfaces, tests need to create a new surface texture without releasing | 540 // surfaces, tests need to create a new surface texture without releasing |
| 480 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle | 541 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle |
| 481 // between two surface textures, only replacing the N-2 texture. Assumption is | 542 // between two surface textures, only replacing the N-2 texture. Assumption is |
| 482 // that no more than N-1 texture is in use by decoder when | 543 // that no more than N-1 texture is in use by decoder when |
| 483 // CreateNextTextureAndSetVideoSurface() is called. | 544 // CreateNextTextureAndSetVideoSurface() is called. |
| 484 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; | 545 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; |
| 485 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; | 546 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; |
| 486 bool surface_texture_a_is_next_; | 547 bool surface_texture_a_is_next_; |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1372 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); | 1433 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); |
| 1373 MediaDecoderJob* second_job = GetMediaDecoderJob(false); | 1434 MediaDecoderJob* second_job = GetMediaDecoderJob(false); |
| 1374 EXPECT_NE(first_job, second_job); | 1435 EXPECT_NE(first_job, second_job); |
| 1375 EXPECT_TRUE(second_job); | 1436 EXPECT_TRUE(second_job); |
| 1376 | 1437 |
| 1377 EXPECT_EQ(3, demuxer_->num_data_requests()); | 1438 EXPECT_EQ(3, demuxer_->num_data_requests()); |
| 1378 EXPECT_EQ(1, demuxer_->num_config_requests()); | 1439 EXPECT_EQ(1, demuxer_->num_config_requests()); |
| 1379 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1440 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 1380 } | 1441 } |
| 1381 | 1442 |
| 1443 TEST_F(MediaSourcePlayerTest, ReleaseClearsSurfaceChangeAndPrefetchDone) { | |
| 1444 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1445 | |
| 1446 // Test that Release() clears both a pending surface change event as well | |
| 1447 // as a pending prefetch done event. | |
| 1448 StartVideoDecoderJob(); | |
| 1449 CreateNextTextureAndSetVideoSurface(); | |
| 1450 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1451 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1452 | |
| 1453 EXPECT_FALSE(IsPendingSurfaceChange()); | |
| 1454 CreateNextTextureAndSetVideoSurface(); | |
| 1455 EXPECT_TRUE(IsPendingSurfaceChange()); | |
| 1456 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1457 | |
| 1458 player_.Release(); | |
| 1459 EXPECT_FALSE(IsPendingSurfaceChange()); | |
| 1460 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1461 | |
| 1462 // Player should have no decoder job until after Start() and setting non-empty | |
| 1463 // surface. | |
| 1464 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1465 EXPECT_FALSE(player_.IsPlaying()); | |
| 1466 StartVideoDecoderJob(); | |
| 1467 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1468 CreateNextTextureAndSetVideoSurface(); | |
| 1469 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1470 } | |
| 1471 | |
| 1472 TEST_F(MediaSourcePlayerTest, ReleaseWithOnPrefetchDoneAlreadyPosted) { | |
| 1473 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1474 | |
| 1475 // Test that if OnPrefetchDone() had already been posted before and is | |
| 1476 // executed after Release(), player does not DCHECK. | |
| 1477 StartAudioDecoderJob(); | |
| 1478 | |
| 1479 // Escape the original prefetch by decoding a single access unit. | |
| 1480 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
| 1481 message_loop_.Run(); | |
| 1482 | |
| 1483 // Prime the job with a few more access units, so that a later prefetch, | |
| 1484 // triggered by starvation to simulate decoder underrun, can trivially | |
| 1485 // post task to run OnPrefetchDone(). | |
| 1486 player_.OnDemuxerDataAvailable( | |
| 1487 CreateReadFromDemuxerAckWithConfigChanged(true, 4)); | |
| 1488 | |
| 1489 EXPECT_TRUE(GetMediaDecoderJob(true) && | |
| 1490 GetMediaDecoderJob(true)->is_decoding()); | |
| 1491 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 1492 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1493 | |
| 1494 // Simulate decoder underrun, so trivial prefetch starts while still decoding. | |
| 1495 // The prefetch and posting of OnPrefetchDone() will not occur until next | |
| 1496 // MediaDecoderCallBack() occurs. | |
| 1497 TriggerPlayerStarvation(); | |
| 1498 EXPECT_TRUE(IsPendingPrefetchRequest()); | |
| 1499 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1500 | |
| 1501 // Upon the next successful decode callback, post a task to Release() | |
| 1502 // |player_|, such that the trivial OnPrefetchDone() task posting also occurs | |
| 1503 // and should execute after the Release(). | |
| 1504 manager_.HookNextMediaDecoderCallback(media::BindToLoop( | |
| 1505 message_loop_.message_loop_proxy(), | |
| 1506 base::Bind( | |
| 1507 &MediaSourcePlayerTest_ReleaseWithOnPrefetchDoneAlreadyPosted_Test:: | |
| 1508 ReleaseWithPendingPrefetchDoneVerification, | |
| 1509 base::Unretained(this)))); | |
| 1510 | |
| 1511 while (GetMediaDecoderJob(true)) | |
| 1512 message_loop_.RunUntilIdle(); | |
| 1513 EXPECT_TRUE(decoder_callback_hook_executed_); | |
| 1514 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 1515 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1516 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1517 EXPECT_FALSE(player_.IsPlaying()); | |
| 1518 | |
| 1519 // Player should have no decoder job until after Start(). | |
| 1520 StartAudioDecoderJob(); | |
| 1521 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1522 } | |
| 1523 | |
| 1524 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekAndDone) { | |
| 1525 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1526 | |
| 1527 // Test that if Release() occurs after SeekTo(), but the DemuxerSeek IPC | |
| 1528 // request has not yet been sent, that the seek request will be sent after | |
| 1529 // Release(). Also, if OnDemuxerSeekDone() occurs prior to next Start(), then | |
| 1530 // the player will resume correct post-seek preroll upon Start(). | |
| 1531 StartAudioDecoderJob(); | |
| 1532 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1533 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1534 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
| 1535 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1536 | |
| 1537 // SeekTo() while the job is decoding, so DemuxerSeek IPC transmission pends | |
| 1538 // decoder completion (or player Release()). | |
| 1539 player_.SeekTo(base::TimeDelta::FromMilliseconds(100)); | |
| 1540 EXPECT_TRUE(IsPendingSeek()); | |
| 1541 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1542 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
| 1543 | |
| 1544 // TODO(qinmin/wolenetz): Don't drop previously received data. See | |
| 1545 // http://crbug.com/306314 and http://crbug.com/304234. | |
| 1546 player_.Release(); | |
| 1547 EXPECT_FALSE(player_.IsPlaying()); | |
| 1548 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1549 EXPECT_TRUE(IsPendingSeek()); | |
| 1550 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1551 | |
| 1552 player_.OnDemuxerSeekDone(kNoTimestamp()); | |
| 1553 EXPECT_FALSE(IsPendingSeek()); | |
| 1554 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1555 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1556 EXPECT_FALSE(player_.IsPlaying()); | |
| 1557 | |
| 1558 // Player should begin prefetch and resume preroll upon Start(). | |
| 1559 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1560 StartAudioDecoderJob(); | |
| 1561 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1562 EXPECT_FALSE(IsPendingSeek()); | |
| 1563 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1564 EXPECT_TRUE(IsPrerolling(true)); | |
| 1565 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1566 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1567 | |
| 1568 // No further seek should have been requested since Release(), above. | |
| 1569 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1570 } | |
| 1571 | |
| 1572 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekThenStart) { | |
| 1573 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1574 | |
| 1575 // Test that if Release() occurs after SeekTo(), but the DemuxerSeek IPC | |
| 1576 // request has not yet been sent, that the seek request will be sent after | |
| 1577 // Release(). Also, if OnDemuxerSeekDone() does not occur until after the next | |
| 1578 // Start(), then the player remains pending seek done and, after | |
| 1579 // OnDemuxerSeekDone(), resumes correct post-seek preroll. | |
| 1580 StartAudioDecoderJob(); | |
| 1581 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1582 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1583 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
| 1584 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 1585 | |
| 1586 // SeekTo() while the job is decoding, so DemuxerSeek IPC transmission pends | |
| 1587 // decoder completion (or player Release()). | |
| 1588 player_.SeekTo(base::TimeDelta::FromMilliseconds(100)); | |
| 1589 EXPECT_TRUE(IsPendingSeek()); | |
| 1590 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1591 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
| 1592 | |
| 1593 // TODO(qinmin/wolenetz): Don't drop previously received data. See | |
| 1594 // http://crbug.com/306314 and http://crbug.com/304234. | |
| 1595 player_.Release(); | |
| 1596 EXPECT_FALSE(player_.IsPlaying()); | |
| 1597 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1598 EXPECT_TRUE(IsPendingSeek()); | |
| 1599 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1600 | |
| 1601 // Player should not prefetch upon Start() nor create the decoder job, due to | |
| 1602 // awaiting DemuxerSeekDone. | |
| 1603 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1604 StartAudioDecoderJob(); | |
| 1605 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1606 EXPECT_TRUE(IsPendingSeek()); | |
| 1607 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 1608 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1609 | |
| 1610 player_.OnDemuxerSeekDone(kNoTimestamp()); | |
| 1611 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1612 EXPECT_FALSE(IsPendingSeek()); | |
| 1613 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1614 EXPECT_TRUE(IsPrerolling(true)); | |
| 1615 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1616 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1617 | |
| 1618 // No further seek should have been requested since Release(), above. | |
| 1619 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1620 } | |
| 1621 | |
| 1622 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenConfigsAvailable) { | |
| 1623 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1624 | |
| 1625 // Test that if Release() occurs after |kConfigChanged| detected and new | |
| 1626 // configs requested of demuxer, and the requested configs arrive before | |
| 1627 // the next Start(), then the player completes the pending config change | |
| 1628 // processing on their receipt. | |
| 1629 StartConfigChange(true, true, 0); | |
| 1630 | |
| 1631 player_.Release(); | |
| 1632 EXPECT_FALSE(player_.IsPlaying()); | |
| 1633 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1634 EXPECT_TRUE(IsPendingConfigChange()); | |
| 1635 | |
| 1636 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); | |
| 1637 EXPECT_FALSE(IsPendingConfigChange()); | |
| 1638 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1639 EXPECT_FALSE(player_.IsPlaying()); | |
| 1640 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1641 | |
| 1642 // Player should resume upon Start(), even without further configs supplied. | |
| 1643 player_.Start(); | |
| 1644 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1645 EXPECT_FALSE(IsPendingConfigChange()); | |
| 1646 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1647 EXPECT_TRUE(player_.IsPlaying()); | |
| 1648 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1649 | |
| 1650 // No further config request should have occurred since StartConfigChange(). | |
| 1651 EXPECT_EQ(1, demuxer_->num_config_requests()); | |
| 1652 } | |
| 1653 | |
| 1654 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenStart) { | |
| 1655 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1656 | |
| 1657 // Test that if Release() occurs after |kConfigChanged| detected and new | |
| 1658 // configs requested of demuxer, and the requested configs arrive after the | |
| 1659 // next Start(), then the player pends job creation until the new configs | |
| 1660 // arrive. | |
| 1661 StartConfigChange(true, true, 0); | |
| 1662 | |
| 1663 player_.Release(); | |
| 1664 EXPECT_FALSE(player_.IsPlaying()); | |
| 1665 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1666 EXPECT_TRUE(IsPendingConfigChange()); | |
| 1667 | |
| 1668 player_.Start(); | |
| 1669 EXPECT_TRUE(player_.IsPlaying()); | |
| 1670 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1671 EXPECT_TRUE(IsPendingConfigChange()); | |
| 1672 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1673 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1674 | |
| 1675 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); | |
| 1676 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1677 EXPECT_FALSE(IsPendingConfigChange()); | |
| 1678 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1679 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1680 | |
| 1681 // No further config request should have occurred since StartConfigChange(). | |
| 1682 EXPECT_EQ(1, demuxer_->num_config_requests()); | |
| 1683 } | |
| 1684 | |
| 1685 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenDemuxerSeekDone) { | |
| 1686 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1687 | |
| 1688 // Test that if Release() occurs after a browser seek's DemuxerSeek IPC | |
| 1689 // request has been sent, that the seek survives the Release(). Also, if | |
| 1690 // OnDemuxerSeekDone() occurs prior to the next Start(), then the player will | |
| 1691 // resume correct post-seek preroll upon Start(). | |
| 1692 // Note, the SeekToThenReleaseThenDemuxerSeek* tests, above, cover the | |
| 1693 // case where seek request has not yet been sent at time of Release(). Browser | |
| 1694 // seeks use similar logic, so no extra test coverage is deemed necessary. On | |
| 1695 // removal of browser seeks, consider retaining a regular seek version of this | |
| 1696 // test. | |
| 1697 | |
| 1698 BrowserSeekPlayer(false); | |
| 1699 EXPECT_FALSE(GetMediaDecoderJob(false)); // It is reset pending the seek. | |
| 1700 EXPECT_TRUE(IsPendingSeek()); | |
| 1701 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
| 1702 | |
| 1703 player_.Release(); | |
| 1704 EXPECT_FALSE(player_.IsPlaying()); | |
| 1705 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1706 EXPECT_TRUE(IsPendingSeek()); | |
| 1707 | |
| 1708 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
| 1709 EXPECT_FALSE(player_.IsPlaying()); | |
| 1710 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1711 EXPECT_FALSE(IsPendingSeek()); | |
| 1712 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1713 | |
| 1714 // Player should begin prefetch and resume preroll upon Start(). | |
| 1715 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1716 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 1717 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1718 StartVideoDecoderJob(); | |
| 1719 CreateNextTextureAndSetVideoSurface(); | |
| 1720 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1721 EXPECT_FALSE(IsPendingSeek()); | |
| 1722 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1723 EXPECT_TRUE(IsPrerolling(false)); | |
| 1724 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1725 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
| 1726 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1727 | |
| 1728 // No further seek should have been requested since BrowserSeekPlayer(). | |
| 1729 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1730 } | |
| 1731 | |
| 1732 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenStart) { | |
| 1733 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1734 | |
| 1735 // Test that if Release() occurs after a browser seek's DemuxerSeek IPC | |
| 1736 // request has been sent, that the seek survives the Release(). Also, if | |
| 1737 // OnDemuxerSeekDone() does not occur until after the next Start(), then the | |
| 1738 // player remains pending seek done and, after OnDemuxerSeekDone(), resumes | |
| 1739 // correct post-seek preroll. | |
| 1740 // Note, the SeekToThenReleaseThenDemuxerSeek* tests, above, cover the | |
| 1741 // case where seek request has not yet been sent at time of Release(). Browser | |
| 1742 // seeks use similar logic, so no extra test coverage is deemed necessary. On | |
| 1743 // removal of browser seeks, consider retaining a regular seek version of this | |
| 1744 // test. | |
| 1745 | |
| 1746 // BIG TODO | |
| 1747 BrowserSeekPlayer(false); | |
| 1748 EXPECT_FALSE(GetMediaDecoderJob(false)); // It is reset pending the seek. | |
| 1749 EXPECT_TRUE(IsPendingSeek()); | |
| 1750 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
| 1751 | |
| 1752 player_.Release(); | |
| 1753 EXPECT_FALSE(player_.IsPlaying()); | |
| 1754 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
|
qinmin
2013/10/30 23:07:48
lots of the testing code are testing the same init
wolenetz
2013/10/31 01:39:11
Yes, indeed. I've coalesced many of the duplicate
| |
| 1755 EXPECT_TRUE(IsPendingSeek()); | |
| 1756 | |
| 1757 StartVideoDecoderJob(); | |
| 1758 CreateNextTextureAndSetVideoSurface(); | |
| 1759 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1760 EXPECT_TRUE(IsPendingSeek()); | |
| 1761 EXPECT_FALSE(IsPendingPrefetchRequest()); | |
| 1762 EXPECT_FALSE(IsPendingPrefetchDone()); | |
| 1763 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1764 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1765 | |
| 1766 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
| 1767 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1768 EXPECT_FALSE(IsPendingSeek()); | |
| 1769 EXPECT_TRUE(IsPendingPrefetchDone()); | |
| 1770 EXPECT_TRUE(IsPrerolling(false)); | |
| 1771 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1772 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
| 1773 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1774 | |
| 1775 // No further seek should have been requested since BrowserSeekPlayer(). | |
| 1776 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1777 } | |
| 1778 | |
| 1382 // TODO(xhwang): Enable this test when the test devices are updated. | 1779 // TODO(xhwang): Enable this test when the test devices are updated. |
| 1383 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { | 1780 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { |
| 1384 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { | 1781 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { |
| 1385 LOG(INFO) << "Could not run test - not supported on device."; | 1782 LOG(INFO) << "Could not run test - not supported on device."; |
| 1386 return; | 1783 return; |
| 1387 } | 1784 } |
| 1388 | 1785 |
| 1389 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, | 1786 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
| 1390 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; | 1787 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
| 1391 | 1788 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1446 | 1843 |
| 1447 std::vector<std::string> codec_avc(1, "avc1"); | 1844 std::vector<std::string> codec_avc(1, "avc1"); |
| 1448 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); | 1845 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); |
| 1449 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); | 1846 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); |
| 1450 } | 1847 } |
| 1451 | 1848 |
| 1452 // TODO(xhwang): Are these IsTypeSupported tests device specific? | 1849 // TODO(xhwang): Are these IsTypeSupported tests device specific? |
| 1453 // TODO(xhwang): Add more IsTypeSupported tests. | 1850 // TODO(xhwang): Add more IsTypeSupported tests. |
| 1454 | 1851 |
| 1455 } // namespace media | 1852 } // namespace media |
| OLD | NEW |