Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: media/base/android/media_source_player_unittest.cc

Issue 596093002: Let audio wait for video to finish prerolling after seek (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/base/android/media_source_player.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/android/media_source_player.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698