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

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

Issue 1287423004: MediaCodecPlayer implementation (stage 5 - reconfiguration) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-cleanuptest
Patch Set: Deleted better Created 5 years, 4 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/logging.h" 6 #include "base/logging.h"
7 #include "base/timer/timer.h" 7 #include "base/timer/timer.h"
8 #include "media/base/android/demuxer_android.h" 8 #include "media/base/android/demuxer_android.h"
9 #include "media/base/android/media_codec_bridge.h" 9 #include "media/base/android/media_codec_bridge.h"
10 #include "media/base/android/media_codec_player.h" 10 #include "media/base/android/media_codec_player.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 return (a - b).magnitude().InMilliseconds() <= tolerance_ms; 55 return (a - b).magnitude().InMilliseconds() <= tolerance_ms;
56 } 56 }
57 57
58 // Mock of MediaPlayerManager for testing purpose. 58 // Mock of MediaPlayerManager for testing purpose.
59 59
60 class MockMediaPlayerManager : public MediaPlayerManager { 60 class MockMediaPlayerManager : public MediaPlayerManager {
61 public: 61 public:
62 MockMediaPlayerManager() 62 MockMediaPlayerManager()
63 : playback_completed_(false), 63 : playback_completed_(false),
64 num_seeks_completed_(0), 64 num_seeks_completed_(0),
65 num_video_codec_created_(0),
65 weak_ptr_factory_(this) {} 66 weak_ptr_factory_(this) {}
66 ~MockMediaPlayerManager() override {} 67 ~MockMediaPlayerManager() override {}
67 68
68 MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; } 69 MediaResourceGetter* GetMediaResourceGetter() override { return nullptr; }
69 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return nullptr; } 70 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return nullptr; }
70 71
71 // Regular time update callback, reports current playback time to 72 // Regular time update callback, reports current playback time to
72 // MediaPlayerManager. 73 // MediaPlayerManager.
73 void OnTimeUpdate(int player_id, 74 void OnTimeUpdate(int player_id,
74 base::TimeDelta current_timestamp, 75 base::TimeDelta current_timestamp,
(...skipping 23 matching lines...) Expand all
98 ++num_seeks_completed_; 99 ++num_seeks_completed_;
99 } 100 }
100 void OnError(int player_id, int error) override {} 101 void OnError(int player_id, int error) override {}
101 void OnVideoSizeChanged(int player_id, int width, int height) override {} 102 void OnVideoSizeChanged(int player_id, int width, int height) override {}
102 void OnAudibleStateChanged(int player_id, bool is_audible_now) override {} 103 void OnAudibleStateChanged(int player_id, bool is_audible_now) override {}
103 void OnWaitingForDecryptionKey(int player_id) override {} 104 void OnWaitingForDecryptionKey(int player_id) override {}
104 MediaPlayerAndroid* GetFullscreenPlayer() override { return nullptr; } 105 MediaPlayerAndroid* GetFullscreenPlayer() override { return nullptr; }
105 MediaPlayerAndroid* GetPlayer(int player_id) override { return nullptr; } 106 MediaPlayerAndroid* GetPlayer(int player_id) override { return nullptr; }
106 bool RequestPlay(int player_id) override { return true; } 107 bool RequestPlay(int player_id) override { return true; }
107 108
108 void OnMediaResourcesRequested(int player_id) {} 109 void OnMediaResourcesRequested(int player_id) { ++num_video_codec_created_; }
109 110
110 // Time update callback that reports the internal progress of the stream. 111 // Time update callback that reports the internal progress of the stream.
111 // Implementation dependent, used for testing only. 112 // Implementation dependent, used for testing only.
112 void OnDecodersTimeUpdate(DemuxerStream::Type stream_type, 113 void OnDecodersTimeUpdate(DemuxerStream::Type stream_type,
113 base::TimeDelta now_playing, 114 base::TimeDelta now_playing,
114 base::TimeDelta last_buffered) { 115 base::TimeDelta last_buffered) {
115 PTSTime& hit = first_frame_hit_[stream_type]; 116 render_stat_[stream_type].AddValue(
116 if (hit.is_null()) 117 PTSTime(now_playing, base::TimeTicks::Now()));
117 hit = PTSTime(now_playing, base::TimeTicks::Now());
118 } 118 }
119 119
120 // First frame information 120 // First frame information
121 base::TimeDelta FirstFramePTS(DemuxerStream::Type stream_type) const { 121 base::TimeDelta FirstFramePTS(DemuxerStream::Type stream_type) const {
122 return first_frame_hit_[stream_type].pts; 122 return render_stat_[stream_type].min().pts;
123 } 123 }
124 base::TimeTicks FirstFrameTime(DemuxerStream::Type stream_type) const { 124 base::TimeTicks FirstFrameTime(DemuxerStream::Type stream_type) const {
125 return first_frame_hit_[stream_type].time; 125 return render_stat_[stream_type].min().time;
126 } 126 }
127 127
128 base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() { 128 base::WeakPtr<MockMediaPlayerManager> GetWeakPtr() {
129 return weak_ptr_factory_.GetWeakPtr(); 129 return weak_ptr_factory_.GetWeakPtr();
130 } 130 }
131 131
132 // Conditions to wait for. 132 // Conditions to wait for.
133 bool IsMetadataChanged() const { return media_metadata_.modified; } 133 bool IsMetadataChanged() const { return media_metadata_.modified; }
134 bool IsPlaybackCompleted() const { return playback_completed_; } 134 bool IsPlaybackCompleted() const { return playback_completed_; }
135 bool IsPlaybackStarted() const { return pts_stat_.num_values() > 0; } 135 bool IsPlaybackStarted() const { return pts_stat_.num_values() > 0; }
136 bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const { 136 bool IsPlaybackBeyondPosition(const base::TimeDelta& pts) const {
137 return pts_stat_.max() > pts; 137 return pts_stat_.max() > pts;
138 } 138 }
139 bool IsSeekCompleted() const { return num_seeks_completed_ > 0; } 139 bool IsSeekCompleted() const { return num_seeks_completed_ > 0; }
140 bool HasFirstFrame(DemuxerStream::Type stream_type) const { 140 bool HasFirstFrame(DemuxerStream::Type stream_type) const {
141 return !first_frame_hit_[stream_type].is_null(); 141 return render_stat_[stream_type].num_values() != 0;
142 } 142 }
143 143
144 int num_video_codec_created() const { return num_video_codec_created_; }
145
144 struct MediaMetadata { 146 struct MediaMetadata {
145 base::TimeDelta duration; 147 base::TimeDelta duration;
146 int width; 148 int width;
147 int height; 149 int height;
148 bool modified; 150 bool modified;
149 MediaMetadata() : width(0), height(0), modified(false) {} 151 MediaMetadata() : width(0), height(0), modified(false) {}
150 }; 152 };
151 MediaMetadata media_metadata_; 153 MediaMetadata media_metadata_;
152 154
155 struct PTSTime {
156 base::TimeDelta pts;
157 base::TimeTicks time;
158
159 PTSTime() : pts(), time() {}
160 PTSTime(base::TimeDelta p, base::TimeTicks t) : pts(p), time(t) {}
161 bool is_null() const { return time.is_null(); }
162 bool operator<(const PTSTime& rhs) const { return time < rhs.time; }
163 };
164 Minimax<PTSTime> render_stat_[DemuxerStream::NUM_TYPES];
165
153 Minimax<base::TimeDelta> pts_stat_; 166 Minimax<base::TimeDelta> pts_stat_;
154 167
155 private: 168 private:
156 bool playback_completed_; 169 bool playback_completed_;
157 int num_seeks_completed_; 170 int num_seeks_completed_;
158 171 int num_video_codec_created_;
159 struct PTSTime {
160 base::TimeDelta pts;
161 base::TimeTicks time;
162 PTSTime() : pts(), time() {}
163 PTSTime(base::TimeDelta p, base::TimeTicks t) : pts(p), time(t) {}
164 bool is_null() const { return time.is_null(); }
165 };
166 PTSTime first_frame_hit_[DemuxerStream::NUM_TYPES];
167 172
168 base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_; 173 base::WeakPtrFactory<MockMediaPlayerManager> weak_ptr_factory_;
169 174
170 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); 175 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager);
171 }; 176 };
172 177
173 // Helper method that creates demuxer configuration. 178 // Helper method that creates demuxer configuration.
174 179
175 DemuxerConfigs CreateAudioVideoConfigs(const base::TimeDelta& duration, 180 DemuxerConfigs CreateAudioVideoConfigs(const base::TimeDelta& duration,
176 const gfx::Size& video_size) { 181 const gfx::Size& video_size) {
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 380
376 bool created = false; 381 bool created = false;
377 if (type == DemuxerStream::AUDIO && audio_factory_) 382 if (type == DemuxerStream::AUDIO && audio_factory_)
378 created = audio_factory_->CreateChunk(&chunk, &delay); 383 created = audio_factory_->CreateChunk(&chunk, &delay);
379 else if (type == DemuxerStream::VIDEO && video_factory_) 384 else if (type == DemuxerStream::VIDEO && video_factory_)
380 created = video_factory_->CreateChunk(&chunk, &delay); 385 created = video_factory_->CreateChunk(&chunk, &delay);
381 386
382 if (!created) 387 if (!created)
383 return; 388 return;
384 389
390 // Request key frame after |kConfigChanged|
391 if (type == DemuxerStream::VIDEO && !chunk.demuxer_configs.empty())
392 video_factory_->RequestKeyFrame();
393
385 chunk.type = type; 394 chunk.type = type;
386 395
387 // Post to the Media thread. Use the weak pointer to prevent the data arrival 396 // Post to the Media thread. Use the weak pointer to prevent the data arrival
388 // after the player has been deleted. 397 // after the player has been deleted.
389 GetMediaTaskRunner()->PostDelayedTask( 398 GetMediaTaskRunner()->PostDelayedTask(
390 FROM_HERE, base::Bind(&MockDemuxerAndroid::OnDemuxerDataAvailable, 399 FROM_HERE, base::Bind(&MockDemuxerAndroid::OnDemuxerDataAvailable,
391 weak_factory_.GetWeakPtr(), chunk), 400 weak_factory_.GetWeakPtr(), chunk),
392 delay); 401 delay);
393 } 402 }
394 403
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 // Wait till completion. 847 // Wait till completion.
839 EXPECT_TRUE( 848 EXPECT_TRUE(
840 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted, 849 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
841 base::Unretained(&manager_)), 850 base::Unretained(&manager_)),
842 timeout)); 851 timeout));
843 852
844 EXPECT_LE(duration, manager_.pts_stat_.max()); 853 EXPECT_LE(duration, manager_.pts_stat_.max());
845 } 854 }
846 855
847 // http://crbug.com/518900 856 // http://crbug.com/518900
848 TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekAfterStop) { 857 TEST_F(MediaCodecPlayerTest, AudioSeekAfterStop) {
849 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); 858 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
850 859
851 // Play for 300 ms, then Pause, then Seek to beginning. The playback should 860 // Play for 300 ms, then Pause, then Seek to beginning. The playback should
852 // start from the beginning. 861 // start from the beginning.
853 862
854 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000); 863 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(2000);
855 864
856 demuxer_->SetAudioFactory( 865 demuxer_->SetAudioFactory(
857 scoped_ptr<AudioFactory>(new AudioFactory(duration))); 866 scoped_ptr<AudioFactory>(new AudioFactory(duration)));
858 867
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 980
972 // The playback should start at |seek_position| 981 // The playback should start at |seek_position|
973 EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1)); 982 EXPECT_TRUE(AlmostEqual(seek_position, manager_.pts_stat_.min(), 1));
974 983
975 // The player should have reported the seek completion to the manager. 984 // The player should have reported the seek completion to the manager.
976 EXPECT_TRUE(WaitForCondition(base::Bind( 985 EXPECT_TRUE(WaitForCondition(base::Bind(
977 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_)))); 986 &MockMediaPlayerManager::IsSeekCompleted, base::Unretained(&manager_))));
978 } 987 }
979 988
980 // http://crbug.com/518900 989 // http://crbug.com/518900
981 TEST_F(MediaCodecPlayerTest, DISABLED_AudioSeekWhilePlaying) { 990 TEST_F(MediaCodecPlayerTest, AudioSeekWhilePlaying) {
982 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); 991 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
983 992
984 // Play for 300 ms, then issue several Seek commands in the row. 993 // Play for 300 ms, then issue several Seek commands in the row.
985 // The playback should continue at the last seek position. 994 // The playback should continue at the last seek position.
986 995
987 // To test this condition without analyzing the reported time details 996 // To test this condition without analyzing the reported time details
988 // and without introducing dependency on implementation I make a long (10s) 997 // and without introducing dependency on implementation I make a long (10s)
989 // duration and test that the playback resumes after big time jump (5s) in a 998 // duration and test that the playback resumes after big time jump (5s) in a
990 // short period of time (200 ms). 999 // short period of time (200 ms).
991 base::TimeDelta duration = base::TimeDelta::FromSeconds(10); 1000 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 EXPECT_TRUE( 1109 EXPECT_TRUE(
1101 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted, 1110 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
1102 base::Unretained(&manager_)), 1111 base::Unretained(&manager_)),
1103 reconfigure_timeout)); 1112 reconfigure_timeout));
1104 1113
1105 // Timestamps should not go back. 1114 // Timestamps should not go back.
1106 EXPECT_LE(max_pts_before_removal, manager_.pts_stat_.max()); 1115 EXPECT_LE(max_pts_before_removal, manager_.pts_stat_.max());
1107 } 1116 }
1108 1117
1109 // http://crbug.com/518900 1118 // http://crbug.com/518900
1110 TEST_F(MediaCodecPlayerTest, DISABLED_VideoReleaseAndStart) { 1119 TEST_F(MediaCodecPlayerTest, VideoReleaseAndStart) {
1111 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); 1120 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
1112 1121
1113 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000); 1122 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(1000);
1114 1123
1115 ASSERT_TRUE(StartVideoPlayback(duration, "VideoReleaseAndStart")); 1124 ASSERT_TRUE(StartVideoPlayback(duration, "VideoReleaseAndStart"));
1116 1125
1117 // Wait for some time and check statistics. 1126 // Wait for some time and check statistics.
1118 WaitForDelay(base::TimeDelta::FromMilliseconds(200)); 1127 WaitForDelay(base::TimeDelta::FromMilliseconds(200));
1119 1128
1120 // Make sure we played at least 100 ms. 1129 // Make sure we played at least 100 ms.
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
1579 1588
1580 // Play till completion. 1589 // Play till completion.
1581 EXPECT_TRUE( 1590 EXPECT_TRUE(
1582 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted, 1591 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
1583 base::Unretained(&manager_)))); 1592 base::Unretained(&manager_))));
1584 1593
1585 // There should not be any video frames. 1594 // There should not be any video frames.
1586 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO)); 1595 EXPECT_FALSE(manager_.HasFirstFrame(DemuxerStream::VIDEO));
1587 } 1596 }
1588 1597
1598 TEST_F(MediaCodecPlayerTest, AVConfigChangeWhilePlaying) {
1599 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
1600
1601 // Test that playback continues after video config change.
1602
1603 // Initialize A/V playback
1604 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(800);
1605 base::TimeDelta config_change_position =
1606 base::TimeDelta::FromMilliseconds(400);
1607
1608 base::TimeDelta start_timeout = base::TimeDelta::FromMilliseconds(2000);
1609
1610 demuxer_->SetAudioFactory(
1611 scoped_ptr<AudioFactory>(new AudioFactory(duration)));
1612 demuxer_->SetVideoFactory(
1613 scoped_ptr<VideoFactory>(new VideoFactory(duration)));
1614
1615 demuxer_->video_factory()->RequestConfigChange(config_change_position);
1616
1617 CreatePlayer();
1618 SetVideoSurface();
1619
1620 // Set special testing callback to receive PTS from decoders.
1621 player_->SetDecodersTimeCallbackForTests(
1622 base::Bind(&MockMediaPlayerManager::OnDecodersTimeUpdate,
1623 base::Unretained(&manager_)));
1624
1625 // Wait till the player is initialized on media thread.
1626 EXPECT_TRUE(WaitForCondition(base::Bind(&MockDemuxerAndroid::IsInitialized,
1627 base::Unretained(demuxer_))));
1628
1629 if (!demuxer_->IsInitialized()) {
1630 DVLOG(0) << "AVConfigChangeWhilePlaying: demuxer is not initialized";
1631 return;
1632 }
1633
1634 // Ask decoders to always reconfigure after the player has been initialized.
1635 player_->SetAlwaysReconfigureForTests(DemuxerStream::VIDEO);
1636
1637 // Post configuration after the player has been initialized.
1638 demuxer_->PostInternalConfigs();
1639
1640 // Start and wait for playback.
1641 player_->Start();
1642
1643 // Wait till we start to play.
1644 EXPECT_TRUE(
1645 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackStarted,
1646 base::Unretained(&manager_)),
1647 start_timeout));
1648
1649 // Wait another 100 ms to make sure we are done with initial preroll.
1650 WaitForDelay(base::TimeDelta::FromMilliseconds(100));
1651
1652 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::AUDIO));
1653 EXPECT_FALSE(player_->IsPrerollingForTests(DemuxerStream::VIDEO));
1654
1655 // Wait till completion
1656 EXPECT_TRUE(
1657 WaitForCondition(base::Bind(&MockMediaPlayerManager::IsPlaybackCompleted,
1658 base::Unretained(&manager_)),
1659 base::TimeDelta::FromMilliseconds(2000)));
1660
1661 // The video codec should be recreated upon config changes.
1662 EXPECT_EQ(2, manager_.num_video_codec_created());
1663
1664 // Check that we did not miss video frames
1665 EXPECT_EQ(41, manager_.render_stat_[DemuxerStream::VIDEO].num_values());
1666 }
1667
1589 } // namespace media 1668 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698