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 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 EXPECT_EQ(original_num_seeks + 1, demuxer_->num_seek_requests()); | 477 EXPECT_EQ(original_num_seeks + 1, demuxer_->num_seek_requests()); |
478 } | 478 } |
479 | 479 |
480 // Preroll the decoder job to |target_timestamp|. The first access unit | 480 // Preroll the decoder job to |target_timestamp|. The first access unit |
481 // to decode will have a timestamp equal to |start_timestamp|. | 481 // to decode will have a timestamp equal to |start_timestamp|. |
482 // TODO(qinmin): Add additional test cases for out-of-order decodes. | 482 // TODO(qinmin): Add additional test cases for out-of-order decodes. |
483 // See http://crbug.com/331421. | 483 // See http://crbug.com/331421. |
484 void PrerollDecoderToTime(bool is_audio, | 484 void PrerollDecoderToTime(bool is_audio, |
485 const base::TimeDelta& start_timestamp, | 485 const base::TimeDelta& start_timestamp, |
486 const base::TimeDelta& target_timestamp) { | 486 const base::TimeDelta& target_timestamp) { |
487 EXPECT_EQ(target_timestamp, player_.GetCurrentTime()); | 487 // It is possible that audio rolls past the |target_timestamp|. As a result, |
488 // the current time may be larger than the |target_timestamp| for video as | |
489 // it may not be the clock manager. | |
490 EXPECT_TRUE(!is_audio || target_timestamp == player_.GetCurrentTime()); | |
wolenetz
2014/09/24 20:39:04
nit: Can you more precisely capture the expectatio
qinmin
2014/09/24 22:49:50
added a boolean to indicate whether the decoder is
| |
488 // |start_timestamp| must be smaller than |target_timestamp|. | 491 // |start_timestamp| must be smaller than |target_timestamp|. |
489 EXPECT_LE(start_timestamp, target_timestamp); | 492 EXPECT_LE(start_timestamp, target_timestamp); |
490 DemuxerData data = is_audio ? CreateReadFromDemuxerAckForAudio(1) : | 493 DemuxerData data = is_audio ? CreateReadFromDemuxerAckForAudio(1) : |
491 CreateReadFromDemuxerAckForVideo(); | 494 CreateReadFromDemuxerAckForVideo(); |
492 int current_timestamp = start_timestamp.InMilliseconds(); | 495 int current_timestamp = start_timestamp.InMilliseconds(); |
493 | 496 |
494 // Send some data with access unit timestamps before the |target_timestamp|, | 497 // Send some data with access unit timestamps before the |target_timestamp|, |
495 // and continue sending the data until preroll finishes. | 498 // and continue sending the data until preroll finishes. |
496 // This simulates the common condition that AUs received after browser | 499 // This simulates the common condition that AUs received after browser |
497 // seek begin with timestamps before the seek target, and don't | 500 // seek begin with timestamps before the seek target, and don't |
498 // immediately complete preroll. | 501 // immediately complete preroll. |
499 while (IsPrerolling(is_audio)) { | 502 while (IsPrerolling(is_audio)) { |
500 data.access_units[0].timestamp = | 503 data.access_units[0].timestamp = |
501 base::TimeDelta::FromMilliseconds(current_timestamp); | 504 base::TimeDelta::FromMilliseconds(current_timestamp); |
502 player_.OnDemuxerDataAvailable(data); | 505 player_.OnDemuxerDataAvailable(data); |
503 EXPECT_TRUE(GetMediaDecoderJob(is_audio)->is_decoding()); | 506 EXPECT_TRUE(GetMediaDecoderJob(is_audio)->is_decoding()); |
504 EXPECT_TRUE(GetMediaCodecBridge(is_audio)); | 507 EXPECT_TRUE(GetMediaCodecBridge(is_audio)); |
505 EXPECT_EQ(target_timestamp, player_.GetCurrentTime()); | 508 EXPECT_TRUE(!is_audio || target_timestamp == player_.GetCurrentTime()); |
wolenetz
2014/09/24 20:39:04
nit: ditto
qinmin
2014/09/24 22:49:50
is_clock_manager should handle the case.
On 2014/
| |
506 current_timestamp += 30; | 509 current_timestamp += 30; |
507 WaitForDecodeDone(is_audio, !is_audio); | 510 WaitForDecodeDone(is_audio, !is_audio); |
508 } | 511 } |
509 EXPECT_LE(target_timestamp, player_.GetCurrentTime()); | 512 EXPECT_LE(target_timestamp, player_.GetCurrentTime()); |
510 } | 513 } |
511 | 514 |
512 DemuxerData CreateReadFromDemuxerAckWithConfigChanged( | 515 DemuxerData CreateReadFromDemuxerAckWithConfigChanged( |
513 bool is_audio, | 516 bool is_audio, |
514 int config_unit_index, | 517 int config_unit_index, |
515 const DemuxerConfigs& configs) { | 518 const DemuxerConfigs& configs) { |
(...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1606 EXPECT_EQ(100.0, player_.GetCurrentTime().InMillisecondsF()); | 1609 EXPECT_EQ(100.0, player_.GetCurrentTime().InMillisecondsF()); |
1607 EXPECT_TRUE(IsPrerolling(true)); | 1610 EXPECT_TRUE(IsPrerolling(true)); |
1608 | 1611 |
1609 // Send data after the seek position. | 1612 // Send data after the seek position. |
1610 PrerollDecoderToTime(true, target_timestamp, target_timestamp); | 1613 PrerollDecoderToTime(true, target_timestamp, target_timestamp); |
1611 } | 1614 } |
1612 | 1615 |
1613 TEST_F(MediaSourcePlayerTest, PrerollContinuesAcrossConfigChange) { | 1616 TEST_F(MediaSourcePlayerTest, PrerollContinuesAcrossConfigChange) { |
1614 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1617 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
1615 | 1618 |
1616 // Test decoder job will resume media prerolling if interrupted by | 1619 // Test decoder job will preroll the media to the seek position. |
1617 // |kConfigChanged| and OnDemuxerConfigsAvailable(). | |
1618 StartAudioDecoderJob(); | 1620 StartAudioDecoderJob(); |
1619 | 1621 |
1620 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); | 1622 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); |
1621 EXPECT_TRUE(IsPrerolling(true)); | 1623 EXPECT_TRUE(IsPrerolling(true)); |
1622 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
1623 | |
1624 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | |
wolenetz
2014/09/24 20:39:04
Do we have another test case that covers the case
qinmin
2014/09/24 22:49:50
Wierd, I didn't remember I made any change to this
| |
1625 | |
1626 // In response to data request, simulate that demuxer signals config change by | |
1627 // sending an AU with |kConfigChanged|. | |
1628 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | |
1629 true, 0, configs); | |
1630 player_.OnDemuxerDataAvailable(data); | |
1631 PrerollDecoderToTime( | 1624 PrerollDecoderToTime( |
1632 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100)); | 1625 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100)); |
1633 } | 1626 } |
1634 | 1627 |
1635 TEST_F(MediaSourcePlayerTest, PrerollContinuesAfterUnchangedConfigs) { | 1628 TEST_F(MediaSourcePlayerTest, PrerollContinuesAfterUnchangedConfigs) { |
1636 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1629 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
1637 | 1630 |
1638 // Test decoder job will resume media prerolling if interrupted by a config | 1631 // Test decoder job will resume media prerolling if interrupted by a config |
1639 // change access unit with unchanged configs. | 1632 // change access unit with unchanged configs. |
1640 StartAudioDecoderJob(); | 1633 StartAudioDecoderJob(); |
1641 | 1634 |
1642 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); | 1635 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); |
1643 EXPECT_TRUE(IsPrerolling(true)); | 1636 EXPECT_TRUE(IsPrerolling(true)); |
1644 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | 1637 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
1645 | 1638 |
1646 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); | 1639 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); |
1647 | 1640 |
1648 // In response to data request, simulate that demuxer signals config change by | 1641 // In response to data request, simulate that demuxer signals config change by |
1649 // sending an AU with |kConfigChanged|. | 1642 // sending an AU with |kConfigChanged|. |
1650 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | 1643 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( |
1651 true, 0, configs); | 1644 true, 0, configs); |
1652 player_.OnDemuxerDataAvailable(data); | 1645 player_.OnDemuxerDataAvailable(data); |
1653 PrerollDecoderToTime( | 1646 PrerollDecoderToTime( |
1654 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100)); | 1647 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100)); |
1655 } | 1648 } |
1656 | 1649 |
1650 TEST_F(MediaSourcePlayerTest, AudioPrerollFinishesBeforeVideo) { | |
1651 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1652 | |
1653 // Test that after audio finishes prerolling, it will wait for video to finish | |
1654 // prerolling before advancing together. | |
1655 CreateNextTextureAndSetVideoSurface(); | |
1656 Start(CreateAudioVideoDemuxerConfigs()); | |
1657 | |
1658 // Initiate a seek. | |
1659 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(100); | |
1660 player_.SeekTo(seek_position); | |
1661 player_.OnDemuxerDataAvailable(CreateAbortedAck(true)); | |
1662 player_.OnDemuxerDataAvailable(CreateAbortedAck(false)); | |
1663 WaitForDecodeDone(true, true); | |
1664 | |
1665 // Verify that the seek is requested. | |
1666 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1667 player_.OnDemuxerSeekDone(kNoTimestamp()); | |
1668 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
1669 EXPECT_EQ(player_.GetCurrentTime().InMillisecondsF(), 100.0); | |
1670 EXPECT_EQ(GetPrerollTimestamp().InMillisecondsF(), 100.0); | |
1671 | |
1672 // Send both audio and video data to finish prefetching. | |
1673 base::TimeDelta seek_ack_position = base::TimeDelta::FromMilliseconds(70); | |
1674 DemuxerData audio_data = CreateReadFromDemuxerAckForAudio(0); | |
1675 audio_data.access_units[0].timestamp = seek_ack_position; | |
1676 DemuxerData video_data = CreateReadFromDemuxerAckForVideo(); | |
1677 video_data.access_units[0].timestamp = seek_ack_position; | |
1678 player_.OnDemuxerDataAvailable(audio_data); | |
1679 player_.OnDemuxerDataAvailable(video_data); | |
1680 WaitForAudioDecodeDone(); | |
1681 WaitForVideoDecodeDone(); | |
1682 | |
1683 // Send audio data at and after the seek position. Audio should finish | |
1684 // prerolling and stop decoding. | |
1685 EXPECT_EQ(6, demuxer_->num_data_requests()); | |
1686 PrerollDecoderToTime(true, seek_position, seek_position); | |
1687 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
1688 EXPECT_FALSE(IsPrerolling(true)); | |
1689 EXPECT_TRUE(IsPrerolling(false)); | |
1690 | |
1691 // Send video data to let video finish prerolling. | |
1692 PrerollDecoderToTime(false, seek_position, seek_position); | |
1693 EXPECT_FALSE(IsPrerolling(false)); | |
1694 | |
1695 // Both audio and video decoders should start decoding again. | |
1696 player_.OnDemuxerDataAvailable(audio_data); | |
1697 player_.OnDemuxerDataAvailable(video_data); | |
1698 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1699 EXPECT_TRUE(GetMediaDecoderJob(false)->is_decoding()); | |
1700 } | |
1701 | |
1657 TEST_F(MediaSourcePlayerTest, SimultaneousAudioVideoConfigChange) { | 1702 TEST_F(MediaSourcePlayerTest, SimultaneousAudioVideoConfigChange) { |
1658 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1703 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
1659 | 1704 |
1660 // Test that the player allows simultaneous audio and video config change, | 1705 // Test that the player allows simultaneous audio and video config change, |
1661 // such as might occur during OnPrefetchDone() if next access unit for both | 1706 // such as might occur during OnPrefetchDone() if next access unit for both |
1662 // audio and video jobs is |kConfigChanged|. | 1707 // audio and video jobs is |kConfigChanged|. |
1663 CreateNextTextureAndSetVideoSurface(); | 1708 CreateNextTextureAndSetVideoSurface(); |
1664 Start(CreateAudioVideoDemuxerConfigs()); | 1709 Start(CreateAudioVideoDemuxerConfigs()); |
1665 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | 1710 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
1666 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); | 1711 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2191 | 2236 |
2192 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | 2237 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); |
2193 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | 2238 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( |
2194 true, 0, configs); | 2239 true, 0, configs); |
2195 player_.OnDemuxerDataAvailable(data); | 2240 player_.OnDemuxerDataAvailable(data); |
2196 WaitForAudioDecodeDone(); | 2241 WaitForAudioDecodeDone(); |
2197 DecodeAudioDataUntilOutputBecomesAvailable(); | 2242 DecodeAudioDataUntilOutputBecomesAvailable(); |
2198 } | 2243 } |
2199 | 2244 |
2200 } // namespace media | 2245 } // namespace media |
OLD | NEW |