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/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 void SetTestDecodeCallback(const base::Closure& test_decode_cb) { | |
| 188 player_.set_decode_callback_for_testing(test_decode_cb); | |
|
acolwell GONE FROM CHROMIUM
2013/10/31 17:54:00
nit: This is only called in one location. Please j
wolenetz
2013/11/01 20:45:28
I did this to keep MSP::set_decode_callback_for_te
| |
| 189 } | |
| 190 | |
| 191 // Asynch test callback posted upon decode completion to verify that a pending | |
| 192 // prefetch done event is cleared across |player_|'s Release(). This helps | |
| 193 // ensure the ReleaseWithOnPrefetchDoneAlreadyPosted test scenario is met. | |
| 194 void ReleaseWithPendingPrefetchDoneVerification() { | |
| 195 EXPECT_TRUE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); | |
| 196 ReleasePlayer(); | |
| 197 EXPECT_FALSE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); | |
| 198 EXPECT_FALSE(decoder_callback_hook_executed_); | |
| 199 decoder_callback_hook_executed_ = true; | |
| 200 } | |
| 201 | |
| 170 DemuxerConfigs CreateAudioDemuxerConfigs() { | 202 DemuxerConfigs CreateAudioDemuxerConfigs() { |
| 171 DemuxerConfigs configs; | 203 DemuxerConfigs configs; |
| 172 configs.audio_codec = kCodecVorbis; | 204 configs.audio_codec = kCodecVorbis; |
| 173 configs.audio_channels = 2; | 205 configs.audio_channels = 2; |
| 174 configs.audio_sampling_rate = 44100; | 206 configs.audio_sampling_rate = 44100; |
| 175 configs.is_audio_encrypted = false; | 207 configs.is_audio_encrypted = false; |
| 176 configs.duration_ms = kDefaultDurationInMs; | 208 configs.duration_ms = kDefaultDurationInMs; |
| 177 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); | 209 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata"); |
| 178 configs.audio_extra_data = std::vector<uint8>( | 210 configs.audio_extra_data = std::vector<uint8>( |
| 179 buffer->data(), | 211 buffer->data(), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 } | 292 } |
| 261 | 293 |
| 262 DemuxerData CreateAbortedAck(bool is_audio) { | 294 DemuxerData CreateAbortedAck(bool is_audio) { |
| 263 DemuxerData data; | 295 DemuxerData data; |
| 264 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; | 296 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; |
| 265 data.access_units.resize(1); | 297 data.access_units.resize(1); |
| 266 data.access_units[0].status = DemuxerStream::kAborted; | 298 data.access_units[0].status = DemuxerStream::kAborted; |
| 267 return data; | 299 return data; |
| 268 } | 300 } |
| 269 | 301 |
| 302 // Helper method for use at test start. It starts an audio decoder job and | |
| 303 // immediately feeds it some data to decode. Then, without letting the decoder | |
| 304 // job complete a decode cycle, it also starts player SeekTo(). Upon return, | |
| 305 // the player should not yet have sent the DemuxerSeek IPC request, though | |
| 306 // seek event should be pending. The audio decoder job will also still be | |
| 307 // decoding. | |
| 308 void StartAudioDecoderJobAndSeekToWhileDecoding( | |
| 309 const base::TimeDelta& seek_time) { | |
| 310 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 311 EXPECT_FALSE(player_.IsPlaying()); | |
| 312 EXPECT_EQ(0, demuxer_->num_data_requests()); | |
| 313 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 314 EXPECT_EQ(player_.GetCurrentTime(), GetPrerollTimestamp()); | |
| 315 StartAudioDecoderJob(); | |
| 316 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 317 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
| 318 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
| 319 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
| 320 player_.SeekTo(seek_time); | |
| 321 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 322 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 323 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
| 324 } | |
| 325 | |
| 270 // Seek, including simulated receipt of |kAborted| read between SeekTo() | 326 // Seek, including simulated receipt of |kAborted| read between SeekTo() |
| 271 // and OnDemuxerSeekDone(). Use this helper method only when the player | 327 // and OnDemuxerSeekDone(). Use this helper method only when the player |
| 272 // already has created the decoder job. | 328 // already has created the decoder job. |
| 273 void SeekPlayer(bool is_audio, const base::TimeDelta& seek_time) { | 329 void SeekPlayer(bool is_audio, const base::TimeDelta& seek_time) { |
| 274 EXPECT_TRUE(GetMediaDecoderJob(is_audio)); | 330 EXPECT_TRUE(GetMediaDecoderJob(is_audio)); |
| 275 | 331 |
| 276 int original_num_seeks = demuxer_->num_seek_requests(); | 332 int original_num_seeks = demuxer_->num_seek_requests(); |
| 277 int original_num_data_requests = demuxer_->num_data_requests(); | 333 int original_num_data_requests = demuxer_->num_data_requests(); |
| 278 | 334 |
| 279 // Initiate a seek. Skip the round-trip of requesting seek from renderer. | 335 // 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(); | 385 demuxer_->num_browser_seek_requests(); |
| 330 | 386 |
| 331 EXPECT_FALSE(GetMediaDecoderJob(false)); | 387 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 332 CreateNextTextureAndSetVideoSurface(); | 388 CreateNextTextureAndSetVideoSurface(); |
| 333 StartVideoDecoderJob(); | 389 StartVideoDecoderJob(); |
| 334 EXPECT_TRUE(GetMediaDecoderJob(false)); | 390 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 335 expected_num_data_requests++; | 391 expected_num_data_requests++; |
| 336 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | 392 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); |
| 337 | 393 |
| 338 if (trigger_with_release_start) { | 394 if (trigger_with_release_start) { |
| 339 player_.Release(); | 395 ReleasePlayer(); |
| 340 | 396 |
| 341 // Simulate demuxer's response to the video data request. | 397 // Simulate demuxer's response to the video data request. |
| 342 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); | 398 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo()); |
| 343 EXPECT_FALSE(GetMediaDecoderJob(false)); | 399 EXPECT_FALSE(GetMediaDecoderJob(false)); |
| 344 EXPECT_FALSE(player_.IsPlaying()); | 400 EXPECT_FALSE(player_.IsPlaying()); |
| 345 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); | 401 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); |
| 346 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | 402 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); |
| 347 | 403 |
| 348 CreateNextTextureAndSetVideoSurface(); | 404 CreateNextTextureAndSetVideoSurface(); |
| 349 player_.Start(); | 405 player_.Start(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 } | 517 } |
| 462 | 518 |
| 463 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, | 519 bool IsTypeSupported(const std::vector<uint8>& scheme_uuid, |
| 464 const std::string& security_level, | 520 const std::string& security_level, |
| 465 const std::string& container, | 521 const std::string& container, |
| 466 const std::vector<std::string>& codecs) { | 522 const std::vector<std::string>& codecs) { |
| 467 return MediaSourcePlayer::IsTypeSupported( | 523 return MediaSourcePlayer::IsTypeSupported( |
| 468 scheme_uuid, security_level, container, codecs); | 524 scheme_uuid, security_level, container, codecs); |
| 469 } | 525 } |
| 470 | 526 |
| 471 protected: | |
| 472 base::MessageLoop message_loop_; | 527 base::MessageLoop message_loop_; |
| 473 MockMediaPlayerManager manager_; | 528 MockMediaPlayerManager manager_; |
| 474 MockDemuxerAndroid* demuxer_; // Owned by |player_|. | 529 MockDemuxerAndroid* demuxer_; // Owned by |player_|. |
| 475 MediaSourcePlayer player_; | 530 MediaSourcePlayer player_; |
| 476 | 531 |
| 532 // Track whether a possibly asynch decoder callback test hook has run. | |
| 533 bool decoder_callback_hook_executed_; | |
| 534 | |
| 477 // We need to keep the surface texture while the decoder is actively decoding. | 535 // 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 | 536 // Otherwise, it may trigger unexpected crashes on some devices. To switch |
| 479 // surfaces, tests need to create a new surface texture without releasing | 537 // surfaces, tests need to create a new surface texture without releasing |
| 480 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle | 538 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle |
| 481 // between two surface textures, only replacing the N-2 texture. Assumption is | 539 // 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 | 540 // that no more than N-1 texture is in use by decoder when |
| 483 // CreateNextTextureAndSetVideoSurface() is called. | 541 // CreateNextTextureAndSetVideoSurface() is called. |
| 484 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; | 542 scoped_refptr<gfx::SurfaceTexture> surface_texture_a_; |
| 485 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; | 543 scoped_refptr<gfx::SurfaceTexture> surface_texture_b_; |
| 486 bool surface_texture_a_is_next_; | 544 bool surface_texture_a_is_next_; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 905 | 963 |
| 906 TEST_F(MediaSourcePlayerTest, DemuxerDataArrivesAfterRelease) { | 964 TEST_F(MediaSourcePlayerTest, DemuxerDataArrivesAfterRelease) { |
| 907 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 965 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 908 | 966 |
| 909 // Test that the decoder should not crash if demuxer data arrives after | 967 // Test that the decoder should not crash if demuxer data arrives after |
| 910 // Release(). | 968 // Release(). |
| 911 StartAudioDecoderJob(); | 969 StartAudioDecoderJob(); |
| 912 EXPECT_EQ(1, demuxer_->num_data_requests()); | 970 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 913 EXPECT_TRUE(GetMediaDecoderJob(true)); | 971 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 914 | 972 |
| 915 player_.Release(); | 973 ReleasePlayer(); |
| 916 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | 974 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); |
| 917 | 975 |
| 918 // The decoder job should have been released. | 976 // The decoder job should have been released. |
| 919 EXPECT_FALSE(player_.IsPlaying()); | 977 EXPECT_FALSE(player_.IsPlaying()); |
| 920 EXPECT_EQ(1, demuxer_->num_data_requests()); | 978 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 921 | 979 |
| 922 // No seek requests should have occurred. | 980 // No seek requests should have occurred. |
| 923 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 981 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 924 } | 982 } |
| 925 | 983 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 957 TEST_F(MediaSourcePlayerTest, NoSeekForInitialReleaseAndStart) { | 1015 TEST_F(MediaSourcePlayerTest, NoSeekForInitialReleaseAndStart) { |
| 958 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1016 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 959 | 1017 |
| 960 // Test that no seek is requested if player Release() + Start() occurs prior | 1018 // Test that no seek is requested if player Release() + Start() occurs prior |
| 961 // to receiving any data. | 1019 // to receiving any data. |
| 962 CreateNextTextureAndSetVideoSurface(); | 1020 CreateNextTextureAndSetVideoSurface(); |
| 963 StartVideoDecoderJob(); | 1021 StartVideoDecoderJob(); |
| 964 EXPECT_EQ(1, demuxer_->num_data_requests()); | 1022 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 965 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1023 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 966 | 1024 |
| 967 player_.Release(); | 1025 ReleasePlayer(); |
| 968 EXPECT_FALSE(player_.IsPlaying()); | |
| 969 | 1026 |
| 970 // Pass a new non-empty surface. | 1027 // Pass a new non-empty surface. |
| 971 CreateNextTextureAndSetVideoSurface(); | 1028 CreateNextTextureAndSetVideoSurface(); |
| 972 | 1029 |
| 973 player_.Start(); | 1030 player_.Start(); |
| 974 | 1031 |
| 975 // TODO(wolenetz/qinmin): Multiple in-flight data requests for same stream | 1032 // TODO(wolenetz/qinmin): Multiple in-flight data requests for same stream |
| 976 // should be prevented. See http://crbug.com/306314. | 1033 // should be prevented. See http://crbug.com/306314. |
| 977 EXPECT_EQ(2, demuxer_->num_data_requests()); | 1034 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 978 | 1035 |
| 979 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1036 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 980 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1037 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 981 } | 1038 } |
| 982 | 1039 |
| 983 TEST_F(MediaSourcePlayerTest, BrowserSeek_MidStreamReleaseAndStart) { | 1040 TEST_F(MediaSourcePlayerTest, BrowserSeek_MidStreamReleaseAndStart) { |
| 984 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | 1041 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); |
| 985 | 1042 |
| 986 // Test that one browser seek is requested if player Release() + Start(), with | 1043 // Test that one browser seek is requested if player Release() + Start(), with |
| 987 // video data received between Release() and Start(). | 1044 // video data received between Release() and Start(). |
| 988 BrowserSeekPlayer(true); | 1045 BrowserSeekPlayer(true); |
| 989 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 990 EXPECT_EQ(1, demuxer_->num_data_requests()); | 1046 EXPECT_EQ(1, demuxer_->num_data_requests()); |
| 991 | 1047 |
| 992 // Simulate browser seek is done and confirm player requests more data. | 1048 // Simulate browser seek is done and confirm player requests more data. |
| 993 player_.OnDemuxerSeekDone(base::TimeDelta()); | 1049 player_.OnDemuxerSeekDone(base::TimeDelta()); |
| 994 EXPECT_TRUE(GetMediaDecoderJob(false)); | 1050 EXPECT_TRUE(GetMediaDecoderJob(false)); |
| 995 EXPECT_EQ(2, demuxer_->num_data_requests()); | 1051 EXPECT_EQ(2, demuxer_->num_data_requests()); |
| 996 EXPECT_EQ(1, demuxer_->num_seek_requests()); | 1052 EXPECT_EQ(1, demuxer_->num_seek_requests()); |
| 997 } | 1053 } |
| 998 | 1054 |
| 999 TEST_F(MediaSourcePlayerTest, PrerollAudioAfterSeek) { | 1055 TEST_F(MediaSourcePlayerTest, PrerollAudioAfterSeek) { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1133 if (i == 1) { | 1189 if (i == 1) { |
| 1134 // While still prerolling, Release() and Start() the player. | 1190 // While still prerolling, Release() and Start() the player. |
| 1135 // TODO(qinmin): Simulation of multiple in-flight data requests (one from | 1191 // TODO(qinmin): Simulation of multiple in-flight data requests (one from |
| 1136 // before Release(), one from after Start()) is not included here, and | 1192 // before Release(), one from after Start()) is not included here, and |
| 1137 // neither is any data enqueued for later decode if it arrives after | 1193 // neither is any data enqueued for later decode if it arrives after |
| 1138 // Release() and before Start(). See http://crbug.com/306314. Assumption | 1194 // Release() and before Start(). See http://crbug.com/306314. Assumption |
| 1139 // for this test, to prevent flakiness until the bug is fixed, is the | 1195 // 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 | 1196 // first request's data arrives before Start(). Though that data is not |
| 1141 // seen by decoder, this assumption allows preroll continuation | 1197 // seen by decoder, this assumption allows preroll continuation |
| 1142 // verification and prevents multiple in-flight data requests. | 1198 // verification and prevents multiple in-flight data requests. |
| 1143 player_.Release(); | 1199 ReleasePlayer(); |
| 1144 player_.OnDemuxerDataAvailable(data); | 1200 player_.OnDemuxerDataAvailable(data); |
| 1145 message_loop_.RunUntilIdle(); | 1201 message_loop_.RunUntilIdle(); |
| 1146 EXPECT_FALSE(GetMediaDecoderJob(true)); | 1202 EXPECT_FALSE(GetMediaDecoderJob(true)); |
| 1147 StartAudioDecoderJob(); | 1203 StartAudioDecoderJob(); |
| 1148 EXPECT_TRUE(GetMediaDecoderJob(true)); | 1204 EXPECT_TRUE(GetMediaDecoderJob(true)); |
| 1149 } else { | 1205 } else { |
| 1150 player_.OnDemuxerDataAvailable(data); | 1206 player_.OnDemuxerDataAvailable(data); |
| 1151 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | 1207 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); |
| 1152 message_loop_.Run(); | 1208 message_loop_.Run(); |
| 1153 } | 1209 } |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1372 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); | 1428 player_.OnDemuxerConfigsAvailable(CreateVideoDemuxerConfigs()); |
| 1373 MediaDecoderJob* second_job = GetMediaDecoderJob(false); | 1429 MediaDecoderJob* second_job = GetMediaDecoderJob(false); |
| 1374 EXPECT_NE(first_job, second_job); | 1430 EXPECT_NE(first_job, second_job); |
| 1375 EXPECT_TRUE(second_job); | 1431 EXPECT_TRUE(second_job); |
| 1376 | 1432 |
| 1377 EXPECT_EQ(3, demuxer_->num_data_requests()); | 1433 EXPECT_EQ(3, demuxer_->num_data_requests()); |
| 1378 EXPECT_EQ(1, demuxer_->num_config_requests()); | 1434 EXPECT_EQ(1, demuxer_->num_config_requests()); |
| 1379 EXPECT_EQ(0, demuxer_->num_seek_requests()); | 1435 EXPECT_EQ(0, demuxer_->num_seek_requests()); |
| 1380 } | 1436 } |
| 1381 | 1437 |
| 1438 TEST_F(MediaSourcePlayerTest, ReleaseWithOnPrefetchDoneAlreadyPosted) { | |
| 1439 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1440 | |
| 1441 // Test that if OnPrefetchDone() had already been posted before and is | |
| 1442 // executed after Release(), player does not DCHECK. | |
| 1443 StartAudioDecoderJob(); | |
| 1444 | |
| 1445 // Escape the original prefetch by decoding a single access unit. | |
| 1446 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
| 1447 message_loop_.Run(); | |
| 1448 | |
| 1449 // Prime the job with a few more access units, so that a later prefetch, | |
| 1450 // triggered by starvation to simulate decoder underrun, can trivially | |
| 1451 // post task to run OnPrefetchDone(). | |
| 1452 player_.OnDemuxerDataAvailable( | |
| 1453 CreateReadFromDemuxerAckWithConfigChanged(true, 4)); | |
| 1454 EXPECT_TRUE(GetMediaDecoderJob(true) && | |
| 1455 GetMediaDecoderJob(true)->is_decoding()); | |
| 1456 | |
| 1457 // Simulate decoder underrun, so trivial prefetch starts while still decoding. | |
| 1458 // The prefetch and posting of OnPrefetchDone() will not occur until next | |
| 1459 // MediaDecoderCallBack() occurs. | |
| 1460 TriggerPlayerStarvation(); | |
| 1461 | |
| 1462 // Upon the next successful decode callback, post a task to Release() | |
|
qinmin
2013/10/31 04:12:27
nit: rephrase this. either "release |player_|" or
wolenetz
2013/11/01 20:45:28
Done.
wolenetz
2013/11/01 20:45:28
Done.
| |
| 1463 // |player_|, such that the trivial OnPrefetchDone() task posting also occurs | |
| 1464 // and should execute after the Release(). | |
| 1465 SetTestDecodeCallback(media::BindToLoop( | |
|
acolwell GONE FROM CHROMIUM
2013/10/31 17:54:00
Do you really need this callback? Can't you just c
wolenetz
2013/11/01 20:45:28
The problem is that RunUntilIdle() runs too much,
| |
| 1466 message_loop_.message_loop_proxy(), | |
| 1467 base::Bind( | |
| 1468 &MediaSourcePlayerTest_ReleaseWithOnPrefetchDoneAlreadyPosted_Test:: | |
| 1469 ReleaseWithPendingPrefetchDoneVerification, | |
| 1470 base::Unretained(this)))); | |
| 1471 | |
| 1472 while (GetMediaDecoderJob(true)) | |
| 1473 message_loop_.RunUntilIdle(); | |
| 1474 EXPECT_TRUE(decoder_callback_hook_executed_); | |
| 1475 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1476 | |
| 1477 // Player should have no decoder job until after Start(). | |
| 1478 StartAudioDecoderJob(); | |
| 1479 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1480 } | |
| 1481 | |
| 1482 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekAndDone) { | |
| 1483 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1484 | |
| 1485 // Test that if Release() occurs after SeekTo(), but the DemuxerSeek IPC | |
| 1486 // request has not yet been sent, that the seek request will be sent after | |
| 1487 // Release(). Also, if OnDemuxerSeekDone() occurs prior to next Start(), then | |
| 1488 // the player will resume correct post-seek preroll upon Start(). | |
| 1489 StartAudioDecoderJobAndSeekToWhileDecoding( | |
| 1490 base::TimeDelta::FromMilliseconds(100)); | |
| 1491 ReleasePlayer(); | |
| 1492 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1493 | |
| 1494 player_.OnDemuxerSeekDone(kNoTimestamp()); | |
| 1495 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1496 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1497 EXPECT_FALSE(player_.IsPlaying()); | |
| 1498 | |
| 1499 // Player should begin prefetch and resume preroll upon Start(). | |
| 1500 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1501 StartAudioDecoderJob(); | |
| 1502 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1503 EXPECT_TRUE(IsPrerolling(true)); | |
| 1504 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1505 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1506 | |
| 1507 // No further seek should have been requested since Release(), above. | |
| 1508 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1509 } | |
| 1510 | |
| 1511 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekThenStart) { | |
| 1512 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1513 | |
| 1514 // Test that if Release() occurs after SeekTo(), but the DemuxerSeek IPC | |
| 1515 // request has not yet been sent, that the seek request will be sent after | |
| 1516 // Release(). Also, if OnDemuxerSeekDone() does not occur until after the next | |
| 1517 // Start(), then the player remains pending seek done and, after | |
| 1518 // OnDemuxerSeekDone(), resumes correct post-seek preroll. | |
| 1519 StartAudioDecoderJobAndSeekToWhileDecoding( | |
| 1520 base::TimeDelta::FromMilliseconds(100)); | |
| 1521 ReleasePlayer(); | |
| 1522 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1523 | |
| 1524 // Player should not prefetch upon Start() nor create the decoder job, due to | |
| 1525 // awaiting DemuxerSeekDone. | |
| 1526 StartAudioDecoderJob(); | |
| 1527 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1528 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1529 | |
| 1530 player_.OnDemuxerSeekDone(kNoTimestamp()); | |
| 1531 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1532 EXPECT_TRUE(IsPrerolling(true)); | |
| 1533 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
| 1534 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1535 | |
| 1536 // No further seek should have been requested since Release(), above. | |
| 1537 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1538 } | |
| 1539 | |
| 1540 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenConfigsAvailable) { | |
| 1541 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1542 | |
| 1543 // Test that if Release() occurs after |kConfigChanged| detected and new | |
| 1544 // configs requested of demuxer, and the requested configs arrive before | |
| 1545 // the next Start(), then the player completes the pending config change | |
| 1546 // processing on their receipt. | |
| 1547 StartConfigChange(true, true, 0); | |
| 1548 ReleasePlayer(); | |
| 1549 | |
| 1550 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); | |
| 1551 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1552 EXPECT_FALSE(player_.IsPlaying()); | |
| 1553 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1554 | |
| 1555 // Player should resume upon Start(), even without further configs supplied. | |
| 1556 player_.Start(); | |
| 1557 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1558 EXPECT_TRUE(player_.IsPlaying()); | |
| 1559 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1560 | |
| 1561 // No further config request should have occurred since StartConfigChange(). | |
| 1562 EXPECT_EQ(1, demuxer_->num_config_requests()); | |
| 1563 } | |
| 1564 | |
| 1565 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenStart) { | |
| 1566 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1567 | |
| 1568 // Test that if Release() occurs after |kConfigChanged| detected and new | |
| 1569 // configs requested of demuxer, and the requested configs arrive after the | |
| 1570 // next Start(), then the player pends job creation until the new configs | |
| 1571 // arrive. | |
| 1572 StartConfigChange(true, true, 0); | |
| 1573 ReleasePlayer(); | |
| 1574 | |
| 1575 player_.Start(); | |
| 1576 EXPECT_TRUE(player_.IsPlaying()); | |
| 1577 EXPECT_FALSE(GetMediaDecoderJob(true)); | |
| 1578 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1579 | |
| 1580 player_.OnDemuxerConfigsAvailable(CreateAudioDemuxerConfigs()); | |
| 1581 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
| 1582 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1583 | |
| 1584 // No further config request should have occurred since StartConfigChange(). | |
| 1585 EXPECT_EQ(1, demuxer_->num_config_requests()); | |
| 1586 } | |
| 1587 | |
| 1588 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenDemuxerSeekDone) { | |
| 1589 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1590 | |
| 1591 // Test that Release() after a browser seek's DemuxerSeek IPC request has been | |
| 1592 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() arrives | |
| 1593 // prior to the next Start()+SetVideoSurface(), then the player will resume | |
| 1594 // correct post-seek preroll upon Start()+SetVideoSurface(). | |
| 1595 // Note, the SeekToThenReleaseThenDemuxerSeek* tests, above, cover the | |
| 1596 // case where seek request has not yet been sent at time of Release(). Browser | |
| 1597 // seeks use similar logic, so no extra test coverage is deemed necessary. On | |
| 1598 // removal of browser seeks, consider retaining a regular seek version of this | |
|
acolwell GONE FROM CHROMIUM
2013/10/31 17:54:00
This is confusing to me. Does this mean a new test
wolenetz
2013/11/01 20:45:28
Oops! My 'Note' comments in these two new BrowserS
| |
| 1599 // test. | |
| 1600 BrowserSeekPlayer(false); | |
| 1601 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
| 1602 ReleasePlayer(); | |
| 1603 | |
| 1604 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
| 1605 EXPECT_FALSE(player_.IsPlaying()); | |
| 1606 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1607 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1608 | |
| 1609 // Player should begin prefetch and resume preroll upon Start(). | |
| 1610 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1611 StartVideoDecoderJob(); | |
| 1612 CreateNextTextureAndSetVideoSurface(); | |
| 1613 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1614 EXPECT_TRUE(IsPrerolling(false)); | |
| 1615 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1616 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
| 1617 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1618 | |
| 1619 // No further seek should have been requested since BrowserSeekPlayer(). | |
| 1620 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1621 } | |
| 1622 | |
| 1623 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenStart) { | |
| 1624 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 1625 | |
| 1626 // Test that Release() after a browser seek's DemuxerSeek IPC request has been | |
| 1627 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() does not | |
| 1628 // occur until after the next Start()+SetVideoSurface(), then the player | |
| 1629 // remains pending seek done and, after OnDemuxerSeekDone(), resumes correct | |
| 1630 // post-seek preroll. | |
| 1631 // Note, the SeekToThenReleaseThenDemuxerSeek* tests, above, cover the | |
| 1632 // case where seek request has not yet been sent at time of Release(). Browser | |
| 1633 // seeks use similar logic, so no extra test coverage is deemed necessary. On | |
| 1634 // removal of browser seeks, consider retaining a regular seek version of this | |
| 1635 // test. | |
|
acolwell GONE FROM CHROMIUM
2013/10/31 17:54:00
ditto
wolenetz
2013/11/01 20:45:28
Done, per above. Thanks!
| |
| 1636 BrowserSeekPlayer(false); | |
| 1637 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
| 1638 ReleasePlayer(); | |
| 1639 | |
| 1640 StartVideoDecoderJob(); | |
| 1641 CreateNextTextureAndSetVideoSurface(); | |
| 1642 EXPECT_FALSE(GetMediaDecoderJob(false)); | |
| 1643 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
| 1644 | |
| 1645 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
| 1646 EXPECT_TRUE(GetMediaDecoderJob(false)); | |
| 1647 EXPECT_TRUE(IsPrerolling(false)); | |
| 1648 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
| 1649 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
| 1650 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
| 1651 | |
| 1652 // No further seek should have been requested since BrowserSeekPlayer(). | |
| 1653 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
| 1654 } | |
| 1655 | |
| 1382 // TODO(xhwang): Enable this test when the test devices are updated. | 1656 // TODO(xhwang): Enable this test when the test devices are updated. |
| 1383 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { | 1657 TEST_F(MediaSourcePlayerTest, DISABLED_IsTypeSupported_Widevine) { |
| 1384 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { | 1658 if (!MediaCodecBridge::IsAvailable() || !MediaDrmBridge::IsAvailable()) { |
| 1385 LOG(INFO) << "Could not run test - not supported on device."; | 1659 LOG(INFO) << "Could not run test - not supported on device."; |
| 1386 return; | 1660 return; |
| 1387 } | 1661 } |
| 1388 | 1662 |
| 1389 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, | 1663 uint8 kWidevineUUID[] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
| 1390 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; | 1664 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
| 1391 | 1665 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1446 | 1720 |
| 1447 std::vector<std::string> codec_avc(1, "avc1"); | 1721 std::vector<std::string> codec_avc(1, "avc1"); |
| 1448 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); | 1722 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L3", kVideoMp4, codec_avc)); |
| 1449 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); | 1723 EXPECT_FALSE(IsTypeSupported(invalid_uuid, "L1", kVideoMp4, codec_avc)); |
| 1450 } | 1724 } |
| 1451 | 1725 |
| 1452 // TODO(xhwang): Are these IsTypeSupported tests device specific? | 1726 // TODO(xhwang): Are these IsTypeSupported tests device specific? |
| 1453 // TODO(xhwang): Add more IsTypeSupported tests. | 1727 // TODO(xhwang): Add more IsTypeSupported tests. |
| 1454 | 1728 |
| 1455 } // namespace media | 1729 } // namespace media |
| OLD | NEW |