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/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 |