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/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "media/base/android/media_codec_bridge.h" | 10 #include "media/base/android/media_codec_bridge.h" |
11 #include "media/base/android/media_drm_bridge.h" | 11 #include "media/base/android/media_drm_bridge.h" |
12 #include "media/base/android/media_player_manager.h" | 12 #include "media/base/android/media_player_manager.h" |
13 #include "media/base/android/media_source_player.h" | 13 #include "media/base/android/media_source_player.h" |
| 14 #include "media/base/bind_to_loop.h" |
14 #include "media/base/decoder_buffer.h" | 15 #include "media/base/decoder_buffer.h" |
15 #include "media/base/test_data_util.h" | 16 #include "media/base/test_data_util.h" |
16 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
17 #include "ui/gl/android/surface_texture.h" | 18 #include "ui/gl/android/surface_texture.h" |
18 | 19 |
19 namespace media { | 20 namespace media { |
20 | 21 |
21 // Helper macro to skip the test if MediaCodecBridge isn't available. | 22 // Helper macro to skip the test if MediaCodecBridge isn't available. |
22 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ | 23 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ |
23 do { \ | 24 do { \ |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 | 136 |
136 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); | 137 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); |
137 }; | 138 }; |
138 | 139 |
139 class MediaSourcePlayerTest : public testing::Test { | 140 class MediaSourcePlayerTest : public testing::Test { |
140 public: | 141 public: |
141 MediaSourcePlayerTest() | 142 MediaSourcePlayerTest() |
142 : manager_(&message_loop_), | 143 : manager_(&message_loop_), |
143 demuxer_(new MockDemuxerAndroid(&message_loop_)), | 144 demuxer_(new MockDemuxerAndroid(&message_loop_)), |
144 player_(0, &manager_, scoped_ptr<DemuxerAndroid>(demuxer_)), | 145 player_(0, &manager_, scoped_ptr<DemuxerAndroid>(demuxer_)), |
| 146 decoder_callback_hook_executed_(false), |
145 surface_texture_a_is_next_(true) {} | 147 surface_texture_a_is_next_(true) {} |
146 virtual ~MediaSourcePlayerTest() {} | 148 virtual ~MediaSourcePlayerTest() {} |
147 | 149 |
148 protected: | 150 protected: |
149 // Get the decoder job from the MediaSourcePlayer. | 151 // Get the decoder job from the MediaSourcePlayer. |
150 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { | 152 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { |
151 if (is_audio) { | 153 if (is_audio) { |
152 return reinterpret_cast<MediaDecoderJob*>( | 154 return reinterpret_cast<MediaDecoderJob*>( |
153 player_.audio_decoder_job_.get()); | 155 player_.audio_decoder_job_.get()); |
154 } | 156 } |
155 return reinterpret_cast<MediaDecoderJob*>( | 157 return reinterpret_cast<MediaDecoderJob*>( |
156 player_.video_decoder_job_.get()); | 158 player_.video_decoder_job_.get()); |
157 } | 159 } |
158 | 160 |
159 // Get the per-job prerolling status from the MediaSourcePlayer's job matching | 161 // 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. | 162 // |is_audio|. Caller must guard against NPE if the player's job is NULL. |
161 bool IsPrerolling(bool is_audio) { | 163 bool IsPrerolling(bool is_audio) { |
162 return GetMediaDecoderJob(is_audio)->prerolling(); | 164 return GetMediaDecoderJob(is_audio)->prerolling(); |
163 } | 165 } |
164 | 166 |
165 // Get the preroll timestamp from the MediaSourcePlayer. | 167 // Get the preroll timestamp from the MediaSourcePlayer. |
166 base::TimeDelta GetPrerollTimestamp() { | 168 base::TimeDelta GetPrerollTimestamp() { |
167 return player_.preroll_timestamp_; | 169 return player_.preroll_timestamp_; |
168 } | 170 } |
169 | 171 |
| 172 // Simulate player has reached starvation timeout. |
| 173 void TriggerPlayerStarvation() { |
| 174 player_.decoder_starvation_callback_.Cancel(); |
| 175 player_.OnDecoderStarved(); |
| 176 } |
| 177 |
| 178 // Release() the player. |
| 179 void ReleasePlayer() { |
| 180 EXPECT_TRUE(player_.IsPlaying()); |
| 181 player_.Release(); |
| 182 EXPECT_FALSE(player_.IsPlaying()); |
| 183 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 184 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 185 } |
| 186 |
| 187 // Upon the next successful decode callback, post a task to call Release() |
| 188 // on the |player_|. TEST_F's do not have access to the private player |
| 189 // members, hence this helper method. |
| 190 // Prevent usage creep of MSP::set_decode_callback_for_testing() by |
| 191 // only using it for the ReleaseWithOnPrefetchDoneAlreadyPosted test. |
| 192 void OnNextTestDecodeCallbackPostTaskToReleasePlayer() { |
| 193 player_.set_decode_callback_for_testing(media::BindToLoop( |
| 194 message_loop_.message_loop_proxy(), |
| 195 base::Bind( |
| 196 &MediaSourcePlayerTest::ReleaseWithPendingPrefetchDoneVerification, |
| 197 base::Unretained(this)))); |
| 198 } |
| 199 |
| 200 // Asynch test callback posted upon decode completion to verify that a pending |
| 201 // prefetch done event is cleared across |player_|'s Release(). This helps |
| 202 // ensure the ReleaseWithOnPrefetchDoneAlreadyPosted test scenario is met. |
| 203 void ReleaseWithPendingPrefetchDoneVerification() { |
| 204 EXPECT_TRUE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); |
| 205 ReleasePlayer(); |
| 206 EXPECT_FALSE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); |
| 207 EXPECT_FALSE(decoder_callback_hook_executed_); |
| 208 decoder_callback_hook_executed_ = true; |
| 209 } |
| 210 |
170 DemuxerConfigs CreateAudioDemuxerConfigs() { | 211 DemuxerConfigs CreateAudioDemuxerConfigs() { |
171 DemuxerConfigs configs; | 212 DemuxerConfigs configs; |
172 configs.audio_codec = kCodecVorbis; | 213 configs.audio_codec = kCodecVorbis; |
173 configs.audio_channels = 2; | 214 configs.audio_channels = 2; |
174 configs.audio_sampling_rate = 44100; | 215 configs.audio_sampling_rate = 44100; |
175 configs.is_audio_encrypted = false; | 216 configs.is_audio_encrypted = false; |
176 configs.duration_ms = kDefaultDurationInMs; | 217 configs.duration_ms = kDefaultDurationInMs; |
177 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); | 218 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); |
178 configs.audio_extra_data = std::vector<uint8>( | 219 configs.audio_extra_data = std::vector<uint8>( |
179 buffer->data(), | 220 buffer->data(), |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 } | 301 } |
261 | 302 |
262 DemuxerData CreateAbortedAck(bool is_audio) { | 303 DemuxerData CreateAbortedAck(bool is_audio) { |
263 DemuxerData data; | 304 DemuxerData data; |
264 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; | 305 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; |
265 data.access_units.resize(1); | 306 data.access_units.resize(1); |
266 data.access_units[0].status = DemuxerStream::kAborted; | 307 data.access_units[0].status = DemuxerStream::kAborted; |
267 return data; | 308 return data; |
268 } | 309 } |
269 | 310 |
| 311 // Helper method for use at test start. It starts an audio decoder job and |
| 312 // immediately feeds it some data to decode. Then, without letting the decoder |
| 313 // job complete a decode cycle, it also starts player SeekTo(). Upon return, |
| 314 // the player should not yet have sent the DemuxerSeek IPC request, though |
| 315 // seek event should be pending. The audio decoder job will also still be |
| 316 // decoding. |
| 317 void StartAudioDecoderJobAndSeekToWhileDecoding( |
| 318 const base::TimeDelta& seek_time) { |
| 319 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 320 EXPECT_FALSE(player_.IsPlaying()); |
| 321 EXPECT_EQ(0, demuxer_->num_data_requests()); |
| 322 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); |
| 323 EXPECT_EQ(player_.GetCurrentTime(), GetPrerollTimestamp()); |
| 324 StartAudioDecoderJob(); |
| 325 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 326 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); |
| 327 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
| 328 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); |
| 329 player_.SeekTo(seek_time); |
| 330 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); |
| 331 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 332 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 333 } |
| 334 |
270 // Seek, including simulated receipt of |kAborted| read between SeekTo() | 335 // Seek, including simulated receipt of |kAborted| read between SeekTo() |
271 // and OnDemuxerSeekDone(). Use this helper method only when the player | 336 // and OnDemuxerSeekDone(). Use this helper method only when the player |
272 // already has created the decoder job. | 337 // already has created the decoder job. |
273 void SeekPlayer(bool is_audio, const base::TimeDelta& seek_time) { | 338 void SeekPlayer(bool is_audio, const base::TimeDelta& seek_time) { |
274 EXPECT_TRUE(GetMediaDecoderJob(is_audio)); | 339 EXPECT_TRUE(GetMediaDecoderJob(is_audio)); |
275 | 340 |
276 int original_num_seeks = demuxer_->num_seek_requests(); | 341 int original_num_seeks = demuxer_->num_seek_requests(); |
277 int original_num_data_requests = demuxer_->num_data_requests(); | 342 int original_num_data_requests = demuxer_->num_data_requests(); |
278 | 343 |
279 // Initiate a seek. Skip the round-trip of requesting seek from renderer. | 344 // Initiate a seek. Skip the round-trip of requesting seek from renderer. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 demuxer_->num_browser_seek_requests(); | 394 demuxer_->num_browser_seek_requests(); |
330 | 395 |
331 EXPECT_FALSE(GetMediaDecoderJob(false)); | 396 EXPECT_FALSE(GetMediaDecoderJob(false)); |
332 CreateNextTextureAndSetVideoSurface(); | 397 CreateNextTextureAndSetVideoSurface(); |
333 StartVideoDecoderJob(); | 398 StartVideoDecoderJob(); |
334 EXPECT_TRUE(GetMediaDecoderJob(false)); | 399 EXPECT_TRUE(GetMediaDecoderJob(false)); |
335 expected_num_data_requests++; | 400 expected_num_data_requests++; |
336 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | 401 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); |
337 | 402 |
338 if (trigger_with_release_start) { | 403 if (trigger_with_release_start) { |
339 player_.Release(); | 404 ReleasePlayer(); |
340 | 405 |
341 // Simulate demuxer's response to the video data request. | 406 // Simulate demuxer's response to the video data request. |
342 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); | 407 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); |
343 EXPECT_FALSE(GetMediaDecoderJob(false)); | 408 EXPECT_FALSE(GetMediaDecoderJob(false)); |
344 EXPECT_FALSE(player_.IsPlaying()); | 409 EXPECT_FALSE(player_.IsPlaying()); |
345 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); | 410 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); |
346 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | 411 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); |
347 | 412 |
348 CreateNextTextureAndSetVideoSurface(); | 413 CreateNextTextureAndSetVideoSurface(); |
349 player_.Start(); | 414 player_.Start(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 } | 526 } |
462 | 527 |
463 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, | 528 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, |
464 const std::string& security_level, | 529 const std::string& security_level, |
465 const std::string& container, | 530 const std::string& container, |
466 const std::vector<std::string>& codecs) { | 531 const std::vector<std::string>& codecs) { |
467 return MediaSourcePlayer::IsTypeSupported( | 532 return MediaSourcePlayer::IsTypeSupported( |
468 scheme_uuid, security_level, container, codecs); | 533 scheme_uuid, security_level, container, codecs); |
469 } | 534 } |
470 | 535 |
471 protected: | |
472 base::MessageLoop message_loop_; | 536 base::MessageLoop message_loop_; |
473 MockMediaPlayerManager manager_; | 537 MockMediaPlayerManager manager_; |
474 MockDemuxerAndroid* demuxer_; // Owned by |player_|. | 538 MockDemuxerAndroid* demuxer_; // Owned by |player_|. |
475 MediaSourcePlayer player_; | 539 MediaSourcePlayer player_; |
476 | 540 |
| 541 // Track whether a possibly asynch decoder callback test hook has run. |
| 542 bool decoder_callback_hook_executed_; |
| 543 |
477 // We need to keep the surface texture while the decoder is actively decoding. | 544 // 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 | 545 // Otherwise, it may trigger unexpected crashes on some devices. To switch |
479 // surfaces, tests need to create a new surface texture without releasing | 546 // surfaces, tests need to create a new surface texture without releasing |
480 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle | 547 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle |
481 // between two surface textures, only replacing the N-2 texture. Assumption is | 548 // 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 | 549 // that no more than N-1 texture is in use by decoder when |
483 // CreateNextTextureAndSetVideoSurface() is called. | 550 // CreateNextTextureAndSetVideoSurface() is called. |
484 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; | 551 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; |
485 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; | 552 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; |
486 bool surface_texture_a_is_next_; | 553 bool surface_texture_a_is_next_; |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 | 972 |
906 TEST_F(MediaSourcePlayerTest, DemuxerDataArrivesAfterRelease) { | 973 TEST_F(MediaSourcePlayerTest, DemuxerDataArrivesAfterRelease) { |
907 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 974 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
908 | 975 |
909 // Test that the decoder should not crash if demuxer data arrives after | 976 // Test that the decoder should not crash if demuxer data arrives after |
910 // Release(). | 977 // Release(). |
911 StartAudioDecoderJob(); | 978 StartAudioDecoderJob(); |
912 EXPECT_EQ(1, demuxer_->num_data_requests()); | 979 EXPECT_EQ(1, demuxer_->num_data_requests()); |
913 EXPECT_TRUE(GetMediaDecoderJob(true)); | 980 EXPECT_TRUE(GetMediaDecoderJob(true)); |
914 | 981 |
915 player_.Release(); | 982 ReleasePlayer(); |
916 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | 983 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
917 | 984 |
918 // The decoder job should have been released. | 985 // The decoder job should have been released. |
919 EXPECT_FALSE(player_.IsPlaying()); | 986 EXPECT_FALSE(player_.IsPlaying()); |
920 EXPECT_EQ(1, demuxer_->num_data_requests()); | 987 EXPECT_EQ(1, demuxer_->num_data_requests()); |
921 | 988 |
922 // No seek requests should have occurred. | 989 // No seek requests should have occurred. |
923 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 990 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
924 } | 991 } |
925 | 992 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 TEST_F(MediaSourcePlayerTest, NoSeekForInitialReleaseAndStart) { | 1024 TEST_F(MediaSourcePlayerTest, NoSeekForInitialReleaseAndStart) { |
958 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1025 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
959 | 1026 |
960 // Test that no seek is requested if player Release() + Start() occurs prior | 1027 // Test that no seek is requested if player Release() + Start() occurs prior |
961 // to receiving any data. | 1028 // to receiving any data. |
962 CreateNextTextureAndSetVideoSurface(); | 1029 CreateNextTextureAndSetVideoSurface(); |
963 StartVideoDecoderJob(); | 1030 StartVideoDecoderJob(); |
964 EXPECT_EQ(1, demuxer_->num_data_requests()); | 1031 EXPECT_EQ(1, demuxer_->num_data_requests()); |
965 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1032 EXPECT_TRUE(GetMediaDecoderJob(false)); |
966 | 1033 |
967 player_.Release(); | 1034 ReleasePlayer(); |
968 EXPECT_FALSE(player_.IsPlaying()); | |
969 | 1035 |
970 // Pass a new non-empty surface. | 1036 // Pass a new non-empty surface. |
971 CreateNextTextureAndSetVideoSurface(); | 1037 CreateNextTextureAndSetVideoSurface(); |
972 | 1038 |
973 player_.Start(); | 1039 player_.Start(); |
974 | 1040 |
975 // TODO(wolenetz/qinmin): Multiple in-flight data requests for same stream | 1041 // TODO(wolenetz/qinmin): Multiple in-flight data requests for same stream |
976 // should be prevented. See http://crbug.com/306314. | 1042 // should be prevented. See http://crbug.com/306314. |
977 EXPECT_EQ(2, demuxer_->num_data_requests()); | 1043 EXPECT_EQ(2, demuxer_->num_data_requests()); |
978 | 1044 |
979 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1045 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
980 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1046 EXPECT_TRUE(GetMediaDecoderJob(false)); |
981 } | 1047 } |
982 | 1048 |
983 TEST_F(MediaSourcePlayerTest, BrowserSeek_MidStreamReleaseAndStart) { | 1049 TEST_F(MediaSourcePlayerTest, BrowserSeek_MidStreamReleaseAndStart) { |
984 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1050 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
985 | 1051 |
986 // Test that one browser seek is requested if player Release() + Start(), with | 1052 // Test that one browser seek is requested if player Release() + Start(), with |
987 // video data received between Release() and Start(). | 1053 // video data received between Release() and Start(). |
988 BrowserSeekPlayer(true); | 1054 BrowserSeekPlayer(true); |
989 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
990 EXPECT_EQ(1, demuxer_->num_data_requests()); | 1055 EXPECT_EQ(1, demuxer_->num_data_requests()); |
991 | 1056 |
992 // Simulate browser seek is done and confirm player requests more data. | 1057 // Simulate browser seek is done and confirm player requests more data. |
993 player_.OnDemuxerSeekDone(base::TimeDelta()); | 1058 player_.OnDemuxerSeekDone(base::TimeDelta()); |
994 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1059 EXPECT_TRUE(GetMediaDecoderJob(false)); |
995 EXPECT_EQ(2, demuxer_->num_data_requests()); | 1060 EXPECT_EQ(2, demuxer_->num_data_requests()); |
996 EXPECT_EQ(1, demuxer_->num_seek_requests()); | 1061 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
997 } | 1062 } |
998 | 1063 |
999 TEST_F(MediaSourcePlayerTest, PrerollAudioAfterSeek) { | 1064 TEST_F(MediaSourcePlayerTest, PrerollAudioAfterSeek) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 if (i == 1) { | 1198 if (i == 1) { |
1134 // While still prerolling, Release() and Start() the player. | 1199 // While still prerolling, Release() and Start() the player. |
1135 // TODO(qinmin): Simulation of multiple in-flight data requests (one from | 1200 // TODO(qinmin): Simulation of multiple in-flight data requests (one from |
1136 // before Release(), one from after Start()) is not included here, and | 1201 // before Release(), one from after Start()) is not included here, and |
1137 // neither is any data enqueued for later decode if it arrives after | 1202 // neither is any data enqueued for later decode if it arrives after |
1138 // Release() and before Start(). See http://crbug.com/306314. Assumption | 1203 // Release() and before Start(). See http://crbug.com/306314. Assumption |
1139 // for this test, to prevent flakiness until the bug is fixed, is the | 1204 // for this test, to prevent flakiness until the bug is fixed, is the |
1140 // first request's data arrives before Start(). Though that data is not | 1205 // first request's data arrives before Start(). Though that data is not |
1141 // seen by decoder, this assumption allows preroll continuation | 1206 // seen by decoder, this assumption allows preroll continuation |
1142 // verification and prevents multiple in-flight data requests. | 1207 // verification and prevents multiple in-flight data requests. |
1143 player_.Release(); | 1208 ReleasePlayer(); |
1144 player_.OnDemuxerDataAvailable(data); | 1209 player_.OnDemuxerDataAvailable(data); |
1145 message_loop_.RunUntilIdle(); | 1210 message_loop_.RunUntilIdle(); |
1146 EXPECT_FALSE(GetMediaDecoderJob(true)); | 1211 EXPECT_FALSE(GetMediaDecoderJob(true)); |
1147 StartAudioDecoderJob(); | 1212 StartAudioDecoderJob(); |
1148 EXPECT_TRUE(GetMediaDecoderJob(true)); | 1213 EXPECT_TRUE(GetMediaDecoderJob(true)); |
1149 } else { | 1214 } else { |
1150 player_.OnDemuxerDataAvailable(data); | 1215 player_.OnDemuxerDataAvailable(data); |
1151 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | 1216 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); |
1152 message_loop_.Run(); | 1217 message_loop_.Run(); |
1153 } | 1218 } |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); | 1437 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); |
1373 MediaDecoderJob* second_job = GetMediaDecoderJob(false); | 1438 MediaDecoderJob* second_job = GetMediaDecoderJob(false); |
1374 EXPECT_NE(first_job, second_job); | 1439 EXPECT_NE(first_job, second_job); |
1375 EXPECT_TRUE(second_job); | 1440 EXPECT_TRUE(second_job); |
1376 | 1441 |
1377 EXPECT_EQ(3, demuxer_->num_data_requests()); | 1442 EXPECT_EQ(3, demuxer_->num_data_requests()); |
1378 EXPECT_EQ(1, demuxer_->num_config_requests()); | 1443 EXPECT_EQ(1, demuxer_->num_config_requests()); |
1379 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1444 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
1380 } | 1445 } |
1381 | 1446 |
| 1447 TEST_F(MediaSourcePlayerTest, ReleaseWithOnPrefetchDoneAlreadyPosted) { |
| 1448 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1449 |
| 1450 // Test if OnPrefetchDone() had already been posted before and is executed |
| 1451 // after Release(), then player does not DCHECK. This test is fragile to |
| 1452 // change to MediaDecoderJob::Prefetch() implementation; it assumes task |
| 1453 // is posted to run |prefetch_cb| if the job already HasData(). |
| 1454 // TODO(wolenetz): Remove MSP::set_decode_callback_for_testing() if this test |
| 1455 // becomes obsolete. See http://crbug.com/304234. |
| 1456 StartAudioDecoderJob(); |
| 1457 |
| 1458 // Escape the original prefetch by decoding a single access unit. |
| 1459 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
| 1460 message_loop_.Run(); |
| 1461 |
| 1462 // Prime the job with a few more access units, so that a later prefetch, |
| 1463 // triggered by starvation to simulate decoder underrun, can trivially |
| 1464 // post task to run OnPrefetchDone(). |
| 1465 player_.OnDemuxerDataAvailable( |
| 1466 CreateReadFromDemuxerAckWithConfigChanged(true, 4)); |
| 1467 EXPECT_TRUE(GetMediaDecoderJob(true) && |
| 1468 GetMediaDecoderJob(true)->is_decoding()); |
| 1469 |
| 1470 // Simulate decoder underrun, so trivial prefetch starts while still decoding. |
| 1471 // The prefetch and posting of OnPrefetchDone() will not occur until next |
| 1472 // MediaDecoderCallBack() occurs. |
| 1473 TriggerPlayerStarvation(); |
| 1474 |
| 1475 // Upon the next successful decode callback, post a task to call Release() on |
| 1476 // the |player_|, such that the trivial OnPrefetchDone() task posting also |
| 1477 // occurs and should execute after the Release(). |
| 1478 OnNextTestDecodeCallbackPostTaskToReleasePlayer(); |
| 1479 |
| 1480 while (GetMediaDecoderJob(true)) |
| 1481 message_loop_.RunUntilIdle(); |
| 1482 EXPECT_TRUE(decoder_callback_hook_executed_); |
| 1483 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1484 |
| 1485 // Player should have no decoder job until after Start(). |
| 1486 StartAudioDecoderJob(); |
| 1487 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1488 } |
| 1489 |
| 1490 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekAndDone) { |
| 1491 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1492 |
| 1493 // Test if Release() occurs after SeekTo(), but the DemuxerSeek IPC request |
| 1494 // has not yet been sent, then the seek request is sent after Release(). Also, |
| 1495 // test if OnDemuxerSeekDone() occurs prior to next Start(), then the player |
| 1496 // will resume correct post-seek preroll upon Start(). |
| 1497 StartAudioDecoderJobAndSeekToWhileDecoding( |
| 1498 base::TimeDelta::FromMilliseconds(100)); |
| 1499 ReleasePlayer(); |
| 1500 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1501 |
| 1502 player_.OnDemuxerSeekDone(kNoTimestamp()); |
| 1503 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1504 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1505 EXPECT_FALSE(player_.IsPlaying()); |
| 1506 |
| 1507 // Player should begin prefetch and resume preroll upon Start(). |
| 1508 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1509 StartAudioDecoderJob(); |
| 1510 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1511 EXPECT_TRUE(IsPrerolling(true)); |
| 1512 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1513 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1514 |
| 1515 // No further seek should have been requested since Release(), above. |
| 1516 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1517 } |
| 1518 |
| 1519 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekThenStart) { |
| 1520 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1521 |
| 1522 // Test if Release() occurs after SeekTo(), but the DemuxerSeek IPC request |
| 1523 // has not yet been sent, then the seek request is sent after Release(). Also, |
| 1524 // test if OnDemuxerSeekDone() does not occur until after the next Start(), |
| 1525 // then the player remains pending seek done until (and resumes correct |
| 1526 // post-seek preroll after) OnDemuxerSeekDone(). |
| 1527 StartAudioDecoderJobAndSeekToWhileDecoding( |
| 1528 base::TimeDelta::FromMilliseconds(100)); |
| 1529 ReleasePlayer(); |
| 1530 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1531 |
| 1532 // Player should not prefetch upon Start() nor create the decoder job, due to |
| 1533 // awaiting DemuxerSeekDone. |
| 1534 StartAudioDecoderJob(); |
| 1535 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1536 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1537 |
| 1538 player_.OnDemuxerSeekDone(kNoTimestamp()); |
| 1539 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1540 EXPECT_TRUE(IsPrerolling(true)); |
| 1541 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1542 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1543 |
| 1544 // No further seek should have been requested since Release(), above. |
| 1545 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1546 } |
| 1547 |
| 1548 TEST_F(MediaSourcePlayerTest, SeekToThenDemuxerSeekThenReleaseThenSeekDone) { |
| 1549 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1550 |
| 1551 // Test if Release() occurs after a SeekTo()'s subsequent DemuxerSeek IPC |
| 1552 // request and OnDemuxerSeekDone() arrives prior to the next Start(), then the |
| 1553 // player will resume correct post-seek preroll upon Start(). |
| 1554 StartAudioDecoderJobAndSeekToWhileDecoding( |
| 1555 base::TimeDelta::FromMilliseconds(100)); |
| 1556 while (GetMediaDecoderJob(true)->is_decoding()) |
| 1557 message_loop_.RunUntilIdle(); |
| 1558 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1559 |
| 1560 ReleasePlayer(); |
| 1561 player_.OnDemuxerSeekDone(kNoTimestamp()); |
| 1562 EXPECT_FALSE(player_.IsPlaying()); |
| 1563 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1564 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1565 |
| 1566 // Player should begin prefetch and resume preroll upon Start(). |
| 1567 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1568 StartAudioDecoderJob(); |
| 1569 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1570 EXPECT_TRUE(IsPrerolling(true)); |
| 1571 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1572 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1573 |
| 1574 // No further seek should have been requested since before Release(), above. |
| 1575 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1576 } |
| 1577 |
| 1578 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenStart) { |
| 1579 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1580 |
| 1581 // Test if Release() occurs after a SeekTo()'s subsequent DemuxerSeeK IPC |
| 1582 // request OnDemuxerSeekDone() does not occur until after the next Start(), |
| 1583 // then the player remains pending seek done until (and resumes correct |
| 1584 // post-seek preroll after) OnDemuxerSeekDone(). |
| 1585 StartAudioDecoderJobAndSeekToWhileDecoding( |
| 1586 base::TimeDelta::FromMilliseconds(100)); |
| 1587 while (GetMediaDecoderJob(true)->is_decoding()) |
| 1588 message_loop_.RunUntilIdle(); |
| 1589 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1590 |
| 1591 ReleasePlayer(); |
| 1592 StartAudioDecoderJob(); |
| 1593 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1594 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1595 |
| 1596 player_.OnDemuxerSeekDone(kNoTimestamp()); |
| 1597 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1598 EXPECT_TRUE(IsPrerolling(true)); |
| 1599 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); |
| 1600 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1601 |
| 1602 // No further seek should have been requested since before Release(), above. |
| 1603 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1604 } |
| 1605 |
| 1606 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenConfigsAvailable) { |
| 1607 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1608 |
| 1609 // Test if Release() occurs after |kConfigChanged| detected, new configs |
| 1610 // requested of demuxer, and the requested configs arrive before the next |
| 1611 // Start(), then the player completes the pending config change processing on |
| 1612 // their receipt. |
| 1613 StartConfigChange(true, true, 0); |
| 1614 ReleasePlayer(); |
| 1615 |
| 1616 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); |
| 1617 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1618 EXPECT_FALSE(player_.IsPlaying()); |
| 1619 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1620 |
| 1621 // Player should resume upon Start(), even without further configs supplied. |
| 1622 player_.Start(); |
| 1623 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1624 EXPECT_TRUE(player_.IsPlaying()); |
| 1625 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1626 |
| 1627 // No further config request should have occurred since StartConfigChange(). |
| 1628 EXPECT_EQ(1, demuxer_->num_config_requests()); |
| 1629 } |
| 1630 |
| 1631 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenStart) { |
| 1632 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1633 |
| 1634 // Test if Release() occurs after |kConfigChanged| detected, new configs |
| 1635 // requested of demuxer, and the requested configs arrive after the next |
| 1636 // Start(), then the player pends job creation until the new configs arrive. |
| 1637 StartConfigChange(true, true, 0); |
| 1638 ReleasePlayer(); |
| 1639 |
| 1640 player_.Start(); |
| 1641 EXPECT_TRUE(player_.IsPlaying()); |
| 1642 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1643 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1644 |
| 1645 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); |
| 1646 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1647 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1648 |
| 1649 // No further config request should have occurred since StartConfigChange(). |
| 1650 EXPECT_EQ(1, demuxer_->num_config_requests()); |
| 1651 } |
| 1652 |
| 1653 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenDemuxerSeekDone) { |
| 1654 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1655 |
| 1656 // Test that Release() after a browser seek's DemuxerSeek IPC request has been |
| 1657 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() occurs |
| 1658 // before the next Start()+SetVideoSurface(), then the player will resume |
| 1659 // correct post-seek preroll upon Start()+SetVideoSurface(). |
| 1660 BrowserSeekPlayer(false); |
| 1661 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); |
| 1662 ReleasePlayer(); |
| 1663 |
| 1664 player_.OnDemuxerSeekDone(expected_preroll_timestamp); |
| 1665 EXPECT_FALSE(player_.IsPlaying()); |
| 1666 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 1667 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); |
| 1668 |
| 1669 // Player should begin prefetch and resume preroll upon Start(). |
| 1670 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1671 StartVideoDecoderJob(); |
| 1672 CreateNextTextureAndSetVideoSurface(); |
| 1673 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 1674 EXPECT_TRUE(IsPrerolling(false)); |
| 1675 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); |
| 1676 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); |
| 1677 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1678 |
| 1679 // No further seek should have been requested since BrowserSeekPlayer(). |
| 1680 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1681 } |
| 1682 |
| 1683 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenStart) { |
| 1684 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 1685 |
| 1686 // Test that Release() after a browser seek's DemuxerSeek IPC request has been |
| 1687 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() does not |
| 1688 // occur until after the next Start()+SetVideoSurface(), then the player |
| 1689 // remains pending seek done until (and resumes correct post-seek preroll |
| 1690 // after) OnDemuxerSeekDone(). |
| 1691 BrowserSeekPlayer(false); |
| 1692 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); |
| 1693 ReleasePlayer(); |
| 1694 |
| 1695 StartVideoDecoderJob(); |
| 1696 CreateNextTextureAndSetVideoSurface(); |
| 1697 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 1698 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 1699 |
| 1700 player_.OnDemuxerSeekDone(expected_preroll_timestamp); |
| 1701 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 1702 EXPECT_TRUE(IsPrerolling(false)); |
| 1703 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); |
| 1704 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); |
| 1705 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 1706 |
| 1707 // No further seek should have been requested since BrowserSeekPlayer(). |
| 1708 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 1709 } |
| 1710 |
1382 // TODO(xhwang): Enable this test when the test devices are updated. | 1711 // TODO(xhwang): Enable this test when the test devices are updated. |
1383 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { | 1712 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { |
1384 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { | 1713 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { |
1385 LOG(INFO) << "Could not run test - not supported on device."; | 1714 LOG(INFO) << "Could not run test - not supported on device."; |
1386 return; | 1715 return; |
1387 } | 1716 } |
1388 | 1717 |
1389 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, | 1718 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
1390 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; | 1719 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
1391 | 1720 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1446 | 1775 |
1447 std::vector<std::string> codec_avc(1, "avc1"); | 1776 std::vector<std::string> codec_avc(1, "avc1"); |
1448 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); | 1777 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); |
1449 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); | 1778 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); |
1450 } | 1779 } |
1451 | 1780 |
1452 // TODO(xhwang): Are these IsTypeSupported tests device specific? | 1781 // TODO(xhwang): Are these IsTypeSupported tests device specific? |
1453 // TODO(xhwang): Add more IsTypeSupported tests. | 1782 // TODO(xhwang): Add more IsTypeSupported tests. |
1454 | 1783 |
1455 } // namespace media | 1784 } // namespace media |
OLD | NEW |