OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/base/android/media_source_player.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <string> | |
10 #include <utility> | |
11 | |
12 #include "base/logging.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/ptr_util.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/strings/stringprintf.h" | |
17 #include "build/build_config.h" | |
18 #include "media/base/android/audio_decoder_job.h" | |
19 #include "media/base/android/media_codec_util.h" | |
20 #include "media/base/android/media_drm_bridge.h" | |
21 #include "media/base/android/media_player_manager.h" | |
22 #include "media/base/android/media_url_interceptor.h" | |
23 #include "media/base/android/sdk_media_codec_bridge.h" | |
24 #include "media/base/android/video_decoder_job.h" | |
25 #include "media/base/bind_to_current_loop.h" | |
26 #include "media/base/decoder_buffer.h" | |
27 #include "media/base/test_data_util.h" | |
28 #include "media/base/timestamp_constants.h" | |
29 #include "testing/gmock/include/gmock/gmock.h" | |
30 #include "ui/gl/android/surface_texture.h" | |
31 | |
32 namespace media { | |
33 | |
34 const base::TimeDelta kDefaultDuration = | |
35 base::TimeDelta::FromMilliseconds(10000); | |
36 | |
37 // TODO(wolenetz/qinmin): Simplify tests with more effective mock usage, and | |
38 // fix flaky pointer-based MDJ inequality testing. See http://crbug.com/327839. | |
39 | |
40 // Mock of MediaPlayerManager for testing purpose. | |
41 class MockMediaPlayerManager : public MediaPlayerManager { | |
42 public: | |
43 explicit MockMediaPlayerManager(base::MessageLoop* message_loop) | |
44 : message_loop_(message_loop), | |
45 playback_completed_(false), | |
46 num_metadata_changes_(0), | |
47 timestamp_updated_(false), | |
48 allow_play_(true) {} | |
49 ~MockMediaPlayerManager() override {} | |
50 | |
51 // MediaPlayerManager implementation. | |
52 MediaResourceGetter* GetMediaResourceGetter() override { return NULL; } | |
53 MediaUrlInterceptor* GetMediaUrlInterceptor() override { return NULL; } | |
54 void OnTimeUpdate(int player_id, | |
55 base::TimeDelta current_time, | |
56 base::TimeTicks current_time_ticks) override { | |
57 timestamp_updated_ = true; | |
58 } | |
59 void OnMediaMetadataChanged(int player_id, | |
60 base::TimeDelta duration, | |
61 int width, | |
62 int height, | |
63 bool success) override { | |
64 num_metadata_changes_++; | |
65 } | |
66 void OnPlaybackComplete(int player_id) override { | |
67 playback_completed_ = true; | |
68 if (message_loop_->is_running()) | |
69 message_loop_->QuitWhenIdle(); | |
70 } | |
71 void OnMediaInterrupted(int player_id) override {} | |
72 void OnBufferingUpdate(int player_id, int percentage) override {} | |
73 void OnSeekComplete(int player_id, | |
74 const base::TimeDelta& current_time) override {} | |
75 void OnError(int player_id, int error) override {} | |
76 void OnVideoSizeChanged(int player_id, int width, int height) override {} | |
77 void OnWaitingForDecryptionKey(int player_id) override {} | |
78 MediaPlayerAndroid* GetFullscreenPlayer() override { return NULL; } | |
79 MediaPlayerAndroid* GetPlayer(int player_id) override { return NULL; } | |
80 void OnDecorderResourcesReleased(int player_id) {} | |
81 | |
82 bool RequestPlay(int player_id, | |
83 base::TimeDelta duration, | |
84 bool has_audio) override { | |
85 return allow_play_; | |
86 } | |
87 | |
88 bool playback_completed() const { | |
89 return playback_completed_; | |
90 } | |
91 | |
92 int num_metadata_changes() const { | |
93 return num_metadata_changes_; | |
94 } | |
95 | |
96 bool timestamp_updated() const { | |
97 return timestamp_updated_; | |
98 } | |
99 | |
100 void ResetTimestampUpdated() { | |
101 timestamp_updated_ = false; | |
102 } | |
103 | |
104 void set_allow_play(bool value) { | |
105 allow_play_ = value; | |
106 } | |
107 | |
108 private: | |
109 base::MessageLoop* message_loop_; | |
110 bool playback_completed_; | |
111 // The number of metadata changes reported by the player. | |
112 int num_metadata_changes_; | |
113 // Playback timestamp was updated. | |
114 bool timestamp_updated_; | |
115 // Whether the manager will allow players that request playing. | |
116 bool allow_play_; | |
117 | |
118 DISALLOW_COPY_AND_ASSIGN(MockMediaPlayerManager); | |
119 }; | |
120 | |
121 class MockDemuxerAndroid : public DemuxerAndroid { | |
122 public: | |
123 explicit MockDemuxerAndroid(base::MessageLoop* message_loop) | |
124 : message_loop_(message_loop), | |
125 num_data_requests_(0), | |
126 num_seek_requests_(0), | |
127 num_browser_seek_requests_(0) {} | |
128 ~MockDemuxerAndroid() override {} | |
129 | |
130 void Initialize(DemuxerAndroidClient* client) override {} | |
131 void RequestDemuxerData(DemuxerStream::Type type) override { | |
132 num_data_requests_++; | |
133 if (message_loop_->is_running()) | |
134 message_loop_->QuitWhenIdle(); | |
135 } | |
136 void RequestDemuxerSeek(const base::TimeDelta& time_to_seek, | |
137 bool is_browser_seek) override { | |
138 num_seek_requests_++; | |
139 if (is_browser_seek) | |
140 num_browser_seek_requests_++; | |
141 } | |
142 | |
143 int num_data_requests() const { return num_data_requests_; } | |
144 int num_seek_requests() const { return num_seek_requests_; } | |
145 int num_browser_seek_requests() const { return num_browser_seek_requests_; } | |
146 | |
147 private: | |
148 base::MessageLoop* message_loop_; | |
149 | |
150 // The number of encoded data requests this object has seen. | |
151 int num_data_requests_; | |
152 | |
153 // The number of regular and browser seek requests this object has seen. | |
154 int num_seek_requests_; | |
155 | |
156 // The number of browser seek requests this object has seen. | |
157 int num_browser_seek_requests_; | |
158 | |
159 DISALLOW_COPY_AND_ASSIGN(MockDemuxerAndroid); | |
160 }; | |
161 | |
162 class MediaSourcePlayerTest : public testing::Test { | |
163 public: | |
164 MediaSourcePlayerTest() | |
165 : manager_(&message_loop_), | |
166 demuxer_(new MockDemuxerAndroid(&message_loop_)), | |
167 player_(0, | |
168 &manager_, | |
169 base::Bind(&MockMediaPlayerManager::OnDecorderResourcesReleased, | |
170 base::Unretained(&manager_)), | |
171 base::WrapUnique(demuxer_), | |
172 GURL()), | |
173 decoder_callback_hook_executed_(false), | |
174 surface_texture_a_is_next_(true) {} | |
175 | |
176 ~MediaSourcePlayerTest() override {} | |
177 | |
178 protected: | |
179 // Get the decoder job from the MediaSourcePlayer. The return value must not | |
180 // be NULL. | |
181 MediaDecoderJob* GetMediaDecoderJob(bool is_audio) { | |
182 if (is_audio) { | |
183 return reinterpret_cast<MediaDecoderJob*>( | |
184 player_.audio_decoder_job_.get()); | |
185 } | |
186 return reinterpret_cast<MediaDecoderJob*>( | |
187 player_.video_decoder_job_.get()); | |
188 } | |
189 | |
190 // Get the MediaCodecBridge from the decoder job. The return value could be | |
191 // NULL if the decoder is not yet created. | |
192 MediaCodecBridge* GetMediaCodecBridge(bool is_audio) { | |
193 if (is_audio) | |
194 return player_.audio_decoder_job_->media_codec_bridge_.get(); | |
195 return player_.video_decoder_job_->media_codec_bridge_.get(); | |
196 } | |
197 | |
198 // Get the per-job prerolling status from the MediaSourcePlayer's job matching | |
199 // |is_audio|. Caller must guard against NPE if the player's job is NULL. | |
200 bool IsPrerolling(bool is_audio) { | |
201 return GetMediaDecoderJob(is_audio)->prerolling_; | |
202 } | |
203 | |
204 // Get the preroll timestamp from the MediaSourcePlayer. | |
205 base::TimeDelta GetPrerollTimestamp() { | |
206 return player_.preroll_timestamp_; | |
207 } | |
208 | |
209 // Simulate player has reached starvation timeout. | |
210 void TriggerPlayerStarvation() { | |
211 player_.decoder_starvation_callback_.Cancel(); | |
212 player_.OnDecoderStarved(); | |
213 } | |
214 | |
215 // Release() the player. | |
216 void ReleasePlayer() { | |
217 EXPECT_TRUE(player_.IsPlaying()); | |
218 player_.Release(); | |
219 EXPECT_FALSE(player_.IsPlaying()); | |
220 } | |
221 | |
222 // Upon the next successful decode callback, post a task to call Release() | |
223 // on the |player_|. TEST_F's do not have access to the private player | |
224 // members, hence this helper method. | |
225 // Prevent usage creep of MSP::set_decode_callback_for_testing() by | |
226 // only using it for the ReleaseWithOnPrefetchDoneAlreadyPosted test. | |
227 void OnNextTestDecodeCallbackPostTaskToReleasePlayer() { | |
228 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | |
229 player_.set_decode_callback_for_testing(media::BindToCurrentLoop( | |
230 base::Bind( | |
231 &MediaSourcePlayerTest::ReleaseWithPendingPrefetchDoneVerification, | |
232 base::Unretained(this)))); | |
233 } | |
234 | |
235 // Asynch test callback posted upon decode completion to verify that a pending | |
236 // prefetch done event is not cleared across |player_|'s Release(). This helps | |
237 // ensure the ReleaseWithOnPrefetchDoneAlreadyPosted test scenario is met. | |
238 void ReleaseWithPendingPrefetchDoneVerification() { | |
239 EXPECT_TRUE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); | |
240 ReleasePlayer(); | |
241 EXPECT_TRUE(player_.IsEventPending(player_.PREFETCH_DONE_EVENT_PENDING)); | |
242 EXPECT_FALSE(decoder_callback_hook_executed_); | |
243 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
244 decoder_callback_hook_executed_ = true; | |
245 } | |
246 | |
247 DemuxerConfigs CreateAudioDemuxerConfigs(AudioCodec audio_codec, | |
248 bool use_low_sample_rate) { | |
249 DemuxerConfigs configs; | |
250 configs.audio_codec = audio_codec; | |
251 configs.audio_channels = 2; | |
252 configs.is_audio_encrypted = false; | |
253 configs.duration = kDefaultDuration; | |
254 | |
255 if (audio_codec == kCodecVorbis) { | |
256 configs.audio_sampling_rate = use_low_sample_rate ? 11025 : 44100; | |
257 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile( | |
258 "vorbis-extradata"); | |
259 configs.audio_extra_data = std::vector<uint8_t>( | |
260 buffer->data(), buffer->data() + buffer->data_size()); | |
261 return configs; | |
262 } | |
263 | |
264 // Other codecs are not yet supported by this helper. | |
265 EXPECT_EQ(audio_codec, kCodecAAC); | |
266 | |
267 configs.audio_sampling_rate = 48000; | |
268 uint8_t aac_extra_data[] = {0x13, 0x10}; | |
269 configs.audio_extra_data = | |
270 std::vector<uint8_t>(aac_extra_data, aac_extra_data + 2); | |
271 return configs; | |
272 } | |
273 | |
274 DemuxerConfigs CreateVideoDemuxerConfigs(bool use_larger_size) { | |
275 DemuxerConfigs configs; | |
276 configs.video_codec = kCodecVP8; | |
277 configs.video_size = | |
278 use_larger_size ? gfx::Size(640, 240) : gfx::Size(320, 240); | |
279 configs.is_video_encrypted = false; | |
280 configs.duration = kDefaultDuration; | |
281 return configs; | |
282 } | |
283 | |
284 DemuxerConfigs CreateAudioVideoDemuxerConfigs() { | |
285 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); | |
286 configs.video_codec = kCodecVP8; | |
287 configs.video_size = gfx::Size(320, 240); | |
288 configs.is_video_encrypted = false; | |
289 return configs; | |
290 } | |
291 | |
292 DemuxerConfigs CreateDemuxerConfigs(bool have_audio, bool have_video) { | |
293 DCHECK(have_audio || have_video); | |
294 | |
295 if (have_audio && !have_video) | |
296 return CreateAudioDemuxerConfigs(kCodecVorbis, false); | |
297 | |
298 if (have_video && !have_audio) | |
299 return CreateVideoDemuxerConfigs(false); | |
300 | |
301 return CreateAudioVideoDemuxerConfigs(); | |
302 } | |
303 | |
304 // Starts an audio decoder job. | |
305 void StartAudioDecoderJob() { | |
306 Start(CreateAudioDemuxerConfigs(kCodecVorbis, false)); | |
307 } | |
308 | |
309 // Starts a video decoder job. | |
310 void StartVideoDecoderJob() { | |
311 Start(CreateVideoDemuxerConfigs(false)); | |
312 } | |
313 | |
314 // Starts decoding the data. | |
315 void Start(const DemuxerConfigs& configs) { | |
316 EXPECT_EQ(demuxer_->num_data_requests(), 0); | |
317 player_.OnDemuxerConfigsAvailable(configs); | |
318 player_.Start(); | |
319 | |
320 EXPECT_TRUE(player_.IsPlaying()); | |
321 int expected_num_requests = (player_.HasAudio() ? 1 : 0) + | |
322 (player_.HasVideo() ? 1 : 0); | |
323 EXPECT_EQ(expected_num_requests, demuxer_->num_data_requests()); | |
324 } | |
325 | |
326 // Resumes decoding the data. Verifies player behavior relative to | |
327 // |expect_player_requests_audio_data| and | |
328 // |expect_player_requests_video_data|. | |
329 void Resume(bool expect_player_requests_audio_data, | |
330 bool expect_player_requests_video_data) { | |
331 EXPECT_FALSE(player_.IsPlaying()); | |
332 EXPECT_TRUE(player_.HasVideo() || player_.HasAudio()); | |
333 int original_num_data_requests = demuxer_->num_data_requests(); | |
334 int expected_request_delta = | |
335 (expect_player_requests_audio_data ? 1 : 0) + | |
336 (expect_player_requests_video_data ? 1 : 0); | |
337 | |
338 player_.Start(); | |
339 | |
340 EXPECT_TRUE(player_.IsPlaying()); | |
341 EXPECT_EQ(original_num_data_requests + expected_request_delta, | |
342 demuxer_->num_data_requests()); | |
343 } | |
344 | |
345 // Keeps decoding audio data until the decoder starts to output samples. | |
346 // Gives up if no audio output after decoding 10 frames. | |
347 void DecodeAudioDataUntilOutputBecomesAvailable() { | |
348 EXPECT_TRUE(player_.IsPlaying()); | |
349 base::TimeDelta current_time = player_.GetCurrentTime(); | |
350 base::TimeDelta start_timestamp = current_time; | |
351 for (int i = 0; i < 10; ++i) { | |
352 manager_.ResetTimestampUpdated(); | |
353 player_.OnDemuxerDataAvailable( | |
354 CreateReadFromDemuxerAckForAudio(i > 3 ? 3 : i)); | |
355 WaitForAudioDecodeDone(); | |
356 base::TimeDelta new_current_time = player_.GetCurrentTime(); | |
357 EXPECT_LE(current_time.InMilliseconds(), | |
358 new_current_time.InMilliseconds()); | |
359 current_time = new_current_time; | |
360 if (manager_.timestamp_updated()) { | |
361 // TODO(qinmin): the current time is from the decoder thread and it does | |
362 // not take the delay from posting the task into consideration. | |
363 // http://crbug.com/421616. | |
364 EXPECT_LE(start_timestamp.InMillisecondsF(), | |
365 new_current_time.InMillisecondsF()); | |
366 return; | |
367 } | |
368 } | |
369 EXPECT_TRUE(false); | |
370 } | |
371 | |
372 AccessUnit CreateAccessUnitWithData(bool is_audio, int audio_packet_id, | |
373 bool use_large_size_video) { | |
374 AccessUnit unit; | |
375 | |
376 unit.status = DemuxerStream::kOk; | |
377 scoped_refptr<DecoderBuffer> buffer; | |
378 if (is_audio) { | |
379 buffer = ReadTestDataFile( | |
380 base::StringPrintf("vorbis-packet-%d", audio_packet_id)); | |
381 } else { | |
382 buffer = ReadTestDataFile( | |
383 use_large_size_video ? "vp8-I-frame-640x240" : "vp8-I-frame-320x240"); | |
384 } | |
385 unit.data = std::vector<uint8_t>(buffer->data(), | |
386 buffer->data() + buffer->data_size()); | |
387 | |
388 if (is_audio) { | |
389 // Vorbis needs 4 extra bytes padding on Android to decode properly. Check | |
390 // NuMediaExtractor.cpp in Android source code. | |
391 uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff}; | |
392 unit.data.insert(unit.data.end(), padding, padding + 4); | |
393 } | |
394 | |
395 return unit; | |
396 } | |
397 | |
398 DemuxerData CreateReadFromDemuxerAckForAudio(int packet_id) { | |
399 DemuxerData data; | |
400 data.type = DemuxerStream::AUDIO; | |
401 data.access_units.resize(1); | |
402 data.access_units[0] = CreateAccessUnitWithData(true, packet_id, false); | |
403 | |
404 return data; | |
405 } | |
406 | |
407 DemuxerData CreateReadFromDemuxerAckForVideo(bool use_large_size) { | |
408 DemuxerData data; | |
409 data.type = DemuxerStream::VIDEO; | |
410 data.access_units.resize(1); | |
411 data.access_units[0] = CreateAccessUnitWithData(false, 0, use_large_size); | |
412 return data; | |
413 } | |
414 | |
415 DemuxerData CreateEOSAck(bool is_audio) { | |
416 DemuxerData data; | |
417 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; | |
418 data.access_units.resize(1); | |
419 data.access_units[0].status = DemuxerStream::kOk; | |
420 data.access_units[0].is_end_of_stream = true; | |
421 return data; | |
422 } | |
423 | |
424 DemuxerData CreateAbortedAck(bool is_audio) { | |
425 DemuxerData data; | |
426 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; | |
427 data.access_units.resize(1); | |
428 data.access_units[0].status = DemuxerStream::kAborted; | |
429 return data; | |
430 } | |
431 | |
432 bool HasData(bool is_audio) { | |
433 return GetMediaDecoderJob(is_audio)->HasData(); | |
434 } | |
435 | |
436 // Helper method for use at test start. It starts an audio decoder job and | |
437 // immediately feeds it some data to decode. Then, without letting the decoder | |
438 // job complete a decode cycle, it also starts player SeekTo(). Upon return, | |
439 // the player should not yet have sent the DemuxerSeek IPC request, though | |
440 // seek event should be pending. The audio decoder job will also still be | |
441 // decoding. | |
442 void StartAudioDecoderJobAndSeekToWhileDecoding( | |
443 const base::TimeDelta& seek_time) { | |
444 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
445 EXPECT_FALSE(player_.IsPlaying()); | |
446 EXPECT_EQ(0, demuxer_->num_data_requests()); | |
447 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
448 EXPECT_EQ(player_.GetCurrentTime(), GetPrerollTimestamp()); | |
449 StartAudioDecoderJob(); | |
450 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
451 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
452 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
453 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
454 player_.SeekTo(seek_time); | |
455 EXPECT_EQ(0.0, GetPrerollTimestamp().InMillisecondsF()); | |
456 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
457 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
458 } | |
459 | |
460 // Seek, including simulated receipt of |kAborted| read between SeekTo() and | |
461 // OnDemuxerSeekDone(). Use this helper method only when the player already | |
462 // has created the media codec bridge. Exactly one request for more data is | |
463 // expected following the seek, so use this helper for players with only audio | |
464 // or only video. | |
465 void SeekPlayerWithAbort(bool is_audio, const base::TimeDelta& seek_time) { | |
466 int original_num_seeks = demuxer_->num_seek_requests(); | |
467 int original_num_data_requests = demuxer_->num_data_requests(); | |
468 | |
469 // Initiate a seek. Skip the round-trip of requesting seek from renderer. | |
470 // Instead behave as if the renderer has asked us to seek. | |
471 player_.SeekTo(seek_time); | |
472 | |
473 // Verify that the seek does not occur until previously outstanding data | |
474 // request is satisfied. | |
475 EXPECT_EQ(original_num_seeks, demuxer_->num_seek_requests()); | |
476 | |
477 // Simulate seeking causes the demuxer to abort the outstanding read | |
478 // caused by the seek. | |
479 player_.OnDemuxerDataAvailable(CreateAbortedAck(is_audio)); | |
480 | |
481 // Wait for the decode job to finish so we can process the seek request. | |
482 WaitForDecodeDone(is_audio, !is_audio); | |
483 | |
484 // Verify that the seek is requested. | |
485 EXPECT_EQ(original_num_seeks + 1, demuxer_->num_seek_requests()); | |
486 | |
487 // Send back the seek done notification. This should trigger the player to | |
488 // call OnReadFromDemuxer() again. | |
489 EXPECT_EQ(original_num_data_requests, demuxer_->num_data_requests()); | |
490 player_.OnDemuxerSeekDone(kNoTimestamp); | |
491 EXPECT_EQ(original_num_data_requests + 1, demuxer_->num_data_requests()); | |
492 | |
493 // No other seek should have been requested. | |
494 EXPECT_EQ(original_num_seeks + 1, demuxer_->num_seek_requests()); | |
495 } | |
496 | |
497 // Preroll the decoder job to |target_timestamp|. The first access unit | |
498 // to decode will have a timestamp equal to |start_timestamp|. | |
499 // |is_clock_manager| indicates whether the decoder serves as the clock | |
500 // manager for the player. | |
501 // TODO(qinmin): Add additional test cases for out-of-order decodes. | |
502 // See http://crbug.com/331421. | |
503 void PrerollDecoderToTime(bool is_audio, | |
504 const base::TimeDelta& start_timestamp, | |
505 const base::TimeDelta& target_timestamp, | |
506 bool is_clock_manager) { | |
507 // For streams with both audio and video, it is possible that audio rolls | |
508 // past the |target_timestamp|. As a result, the current time may be larger | |
509 // than the |target_timestamp| for video as it may not be the clock manager. | |
510 EXPECT_TRUE(!is_clock_manager || | |
511 target_timestamp == player_.GetCurrentTime()); | |
512 // |start_timestamp| must be smaller than |target_timestamp|. | |
513 EXPECT_LE(start_timestamp, target_timestamp); | |
514 DemuxerData data = is_audio ? CreateReadFromDemuxerAckForAudio(1) : | |
515 CreateReadFromDemuxerAckForVideo(false); | |
516 int current_timestamp = start_timestamp.InMilliseconds(); | |
517 | |
518 // Send some data with access unit timestamps before the |target_timestamp|, | |
519 // and continue sending the data until preroll finishes. | |
520 // This simulates the common condition that AUs received after browser | |
521 // seek begin with timestamps before the seek target, and don't | |
522 // immediately complete preroll. | |
523 while (IsPrerolling(is_audio)) { | |
524 data.access_units[0].timestamp = | |
525 base::TimeDelta::FromMilliseconds(current_timestamp); | |
526 player_.OnDemuxerDataAvailable(data); | |
527 EXPECT_TRUE(GetMediaDecoderJob(is_audio)->is_decoding()); | |
528 EXPECT_TRUE(GetMediaCodecBridge(is_audio)); | |
529 EXPECT_TRUE(!is_clock_manager || | |
530 target_timestamp == player_.GetCurrentTime()); | |
531 current_timestamp += 30; | |
532 WaitForDecodeDone(is_audio, !is_audio); | |
533 } | |
534 EXPECT_LE(target_timestamp, player_.GetCurrentTime()); | |
535 } | |
536 | |
537 DemuxerData CreateReadFromDemuxerAckWithConfigChanged( | |
538 bool is_audio, | |
539 int config_unit_index, | |
540 const DemuxerConfigs& configs) { | |
541 DemuxerData data; | |
542 data.type = is_audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; | |
543 data.access_units.resize(config_unit_index + 1); | |
544 | |
545 for (int i = 0; i < config_unit_index; ++i) | |
546 data.access_units[i] = CreateAccessUnitWithData(is_audio, i, false); | |
547 | |
548 data.access_units[config_unit_index].status = DemuxerStream::kConfigChanged; | |
549 data.demuxer_configs.resize(1); | |
550 data.demuxer_configs[0] = configs; | |
551 return data; | |
552 } | |
553 | |
554 // Valid only for video-only player tests. If |trigger_with_release_start| is | |
555 // true, triggers the browser seek with a Release() + video data received + | |
556 // Start() with a new surface. If false, triggers the browser seek by | |
557 // setting a new video surface after beginning decode of received video data. | |
558 // Such data receipt causes possibility that an I-frame is not next, and | |
559 // browser seek results once decode completes and surface change processing | |
560 // begins. | |
561 void BrowserSeekPlayer(bool trigger_with_release_start) { | |
562 int expected_num_data_requests = demuxer_->num_data_requests() + 2; | |
563 int expected_num_seek_requests = demuxer_->num_seek_requests(); | |
564 int expected_num_browser_seek_requests = | |
565 demuxer_->num_browser_seek_requests(); | |
566 | |
567 CreateNextTextureAndSetVideoSurface(); | |
568 StartVideoDecoderJob(); | |
569 if (trigger_with_release_start) { | |
570 // Consume the first frame, so that the next VideoDecoderJob will not | |
571 // inherit the I-frame from the previous decoder. | |
572 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
573 ReleasePlayer(); | |
574 WaitForVideoDecodeDone(); | |
575 | |
576 // Simulate demuxer's response to the video data request. The data will be | |
577 // passed to the next MediaCodecBridge. | |
578 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
579 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
580 EXPECT_FALSE(player_.IsPlaying()); | |
581 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); | |
582 | |
583 CreateNextTextureAndSetVideoSurface(); | |
584 Resume(false, false); | |
585 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
586 | |
587 // Run the message loop so that prefetch will complete. | |
588 while (expected_num_seek_requests == demuxer_->num_seek_requests()) | |
589 base::RunLoop().RunUntilIdle(); | |
590 } else { | |
591 // Simulate demuxer's response to the video data request. | |
592 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
593 | |
594 // While the decoder is decoding, trigger a browser seek by changing | |
595 // surface. Demuxer does not know of browser seek in advance, so no | |
596 // |kAborted| data is required (though |kAborted| can certainly occur for | |
597 // any pending read in reality due to renderer preparing for a regular | |
598 // seek). | |
599 CreateNextTextureAndSetVideoSurface(); | |
600 | |
601 // Browser seek should not begin until decoding has completed. | |
602 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
603 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); | |
604 | |
605 // Wait for the media codec bridge to finish decoding and be reset pending | |
606 // the browser seek. | |
607 WaitForVideoDecodeDone(); | |
608 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
609 } | |
610 | |
611 // Only one browser seek should have been initiated, and no further data | |
612 // should have been requested. | |
613 expected_num_seek_requests++; | |
614 expected_num_browser_seek_requests++; | |
615 EXPECT_EQ(expected_num_seek_requests, demuxer_->num_seek_requests()); | |
616 EXPECT_EQ(expected_num_browser_seek_requests, | |
617 demuxer_->num_browser_seek_requests()); | |
618 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | |
619 } | |
620 | |
621 // Creates a new media codec bridge and feeds it data ending with a | |
622 // |kConfigChanged| access unit. If |config_unit_in_prefetch| is true, sends | |
623 // feeds the config change AU in response to the job's first read request | |
624 // (prefetch). If false, regular data is fed and decoded prior to feeding the | |
625 // config change AU in response to the second data request (after prefetch | |
626 // completed). |config_unit_index| controls which access unit is | |
627 // |kConfigChanged|. If |enable_adaptive_playback| is true, config change will | |
628 // not cause the decoder to recreate the media codec bridge. Otherwise, the | |
629 // decoder has to drain all its data before recreating the new codec. | |
630 void SendConfigChangeToDecoder(bool is_audio, | |
631 bool config_unit_in_prefetch, | |
632 int config_unit_index, | |
633 bool enable_adaptive_playback) { | |
634 EXPECT_FALSE(GetMediaCodecBridge(is_audio)); | |
635 if (is_audio) { | |
636 StartAudioDecoderJob(); | |
637 } else { | |
638 CreateNextTextureAndSetVideoSurface(); | |
639 StartVideoDecoderJob(); | |
640 } | |
641 | |
642 int expected_num_data_requests = demuxer_->num_data_requests(); | |
643 // Feed and decode a standalone access unit so the player exits prefetch. | |
644 if (!config_unit_in_prefetch) { | |
645 if (is_audio) { | |
646 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
647 } else { | |
648 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
649 EnableAdaptiveVideoPlayback(enable_adaptive_playback); | |
650 } | |
651 | |
652 WaitForDecodeDone(is_audio, !is_audio); | |
653 | |
654 // We should have completed the prefetch phase at this point. | |
655 expected_num_data_requests++; | |
656 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | |
657 } | |
658 | |
659 DemuxerConfigs configs = is_audio ? | |
660 CreateAudioDemuxerConfigs(kCodecVorbis, true) : | |
661 CreateVideoDemuxerConfigs(true); | |
662 // Feed and decode access units with data for any units prior to | |
663 // |config_unit_index|, and a |kConfigChanged| unit at that index. | |
664 // Player should prepare to reconfigure the decoder job, and should request | |
665 // new demuxer configs. | |
666 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckWithConfigChanged( | |
667 is_audio, config_unit_index, configs)); | |
668 | |
669 expected_num_data_requests++; | |
670 EXPECT_EQ(expected_num_data_requests, demuxer_->num_data_requests()); | |
671 if (is_audio) | |
672 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
673 else | |
674 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(true)); | |
675 | |
676 // If the adaptive playback setting was not passed to the MediaCodecBridge | |
677 // earlier, do it here. | |
678 if (config_unit_in_prefetch && !is_audio) | |
679 EnableAdaptiveVideoPlayback(enable_adaptive_playback); | |
680 } | |
681 | |
682 // Send a config change to the decoder job and drain the decoder so that the | |
683 // config change is processed. | |
684 void StartConfigChange(bool is_audio, | |
685 bool config_unit_in_prefetch, | |
686 int config_unit_index, | |
687 bool enable_adaptive_playback) { | |
688 SendConfigChangeToDecoder(is_audio, config_unit_in_prefetch, | |
689 config_unit_index, enable_adaptive_playback); | |
690 | |
691 EXPECT_EQ(!config_unit_in_prefetch && !enable_adaptive_playback && | |
692 config_unit_index == 0, IsDrainingDecoder(is_audio)); | |
693 int expected_num_data_requests = demuxer_->num_data_requests(); | |
694 // Run until decoder starts to request new data. | |
695 while (demuxer_->num_data_requests() == expected_num_data_requests) | |
696 base::RunLoop().RunUntilIdle(); | |
697 EXPECT_FALSE(IsDrainingDecoder(is_audio)); | |
698 } | |
699 | |
700 void EnableAdaptiveVideoPlayback(bool enable) { | |
701 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
702 static_cast<VideoCodecBridge*>(GetMediaCodecBridge(false))-> | |
703 set_adaptive_playback_supported_for_testing( | |
704 enable ? 1 : 0); | |
705 } | |
706 | |
707 void CreateNextTextureAndSetVideoSurface() { | |
708 gl::SurfaceTexture* surface_texture; | |
709 if (surface_texture_a_is_next_) { | |
710 surface_texture_a_ = gl::SurfaceTexture::Create(next_texture_id_++); | |
711 surface_texture = surface_texture_a_.get(); | |
712 } else { | |
713 surface_texture_b_ = gl::SurfaceTexture::Create(next_texture_id_++); | |
714 surface_texture = surface_texture_b_.get(); | |
715 } | |
716 | |
717 surface_texture_a_is_next_ = !surface_texture_a_is_next_; | |
718 gl::ScopedJavaSurface surface = gl::ScopedJavaSurface(surface_texture); | |
719 player_.SetVideoSurface(std::move(surface)); | |
720 } | |
721 | |
722 // Wait for one or both of the jobs to complete decoding. Media codec bridges | |
723 // are assumed to exist for any stream whose decode completion is awaited. | |
724 void WaitForDecodeDone(bool wait_for_audio, bool wait_for_video) { | |
725 DCHECK(wait_for_audio || wait_for_video); | |
726 while ((wait_for_audio && GetMediaCodecBridge(true) && | |
727 GetMediaDecoderJob(true)->HasData() && | |
728 GetMediaDecoderJob(true)->is_decoding()) || | |
729 (wait_for_video && GetMediaCodecBridge(false) && | |
730 GetMediaDecoderJob(false)->HasData() && | |
731 GetMediaDecoderJob(false)->is_decoding())) { | |
732 base::RunLoop().RunUntilIdle(); | |
733 } | |
734 } | |
735 | |
736 void WaitForAudioDecodeDone() { | |
737 WaitForDecodeDone(true, false); | |
738 } | |
739 | |
740 void WaitForVideoDecodeDone() { | |
741 WaitForDecodeDone(false, true); | |
742 } | |
743 | |
744 void WaitForAudioVideoDecodeDone() { | |
745 WaitForDecodeDone(true, true); | |
746 } | |
747 | |
748 // If |send_eos| is true, generates EOS for the stream corresponding to | |
749 // |eos_for_audio|. Verifies that playback completes and no further data | |
750 // is requested. | |
751 // If |send_eos| is false, then it is assumed that caller previously arranged | |
752 // for player to receive EOS for each stream, but the player has not yet | |
753 // decoded all of them. In this case, |eos_for_audio| is ignored. | |
754 void VerifyPlaybackCompletesOnEOSDecode(bool send_eos, bool eos_for_audio) { | |
755 int original_num_data_requests = demuxer_->num_data_requests(); | |
756 if (send_eos) | |
757 player_.OnDemuxerDataAvailable(CreateEOSAck(eos_for_audio)); | |
758 EXPECT_FALSE(manager_.playback_completed()); | |
759 base::RunLoop().Run(); | |
760 EXPECT_TRUE(manager_.playback_completed()); | |
761 EXPECT_EQ(original_num_data_requests, demuxer_->num_data_requests()); | |
762 } | |
763 | |
764 void VerifyCompletedPlaybackResumesOnSeekPlusStart(bool have_audio, | |
765 bool have_video) { | |
766 DCHECK(have_audio || have_video); | |
767 | |
768 EXPECT_TRUE(manager_.playback_completed()); | |
769 | |
770 player_.SeekTo(base::TimeDelta()); | |
771 player_.OnDemuxerSeekDone(kNoTimestamp); | |
772 Resume(have_audio, have_video); | |
773 } | |
774 | |
775 // Starts the appropriate decoder jobs according to |have_audio| and | |
776 // |have_video|. Then starts seek during decode of EOS or non-EOS according to | |
777 // |eos_audio| and |eos_video|. Simulates seek completion and verifies that | |
778 // playback never completed. |eos_{audio,video}| is ignored if the | |
779 // corresponding |have_{audio,video}| is false. | |
780 void VerifySeekDuringEOSDecodePreventsPlaybackCompletion(bool have_audio, | |
781 bool have_video, | |
782 bool eos_audio, | |
783 bool eos_video) { | |
784 DCHECK(have_audio || have_video); | |
785 | |
786 if (have_video) | |
787 CreateNextTextureAndSetVideoSurface(); | |
788 | |
789 Start(CreateDemuxerConfigs(have_audio, have_video)); | |
790 | |
791 if (have_audio) | |
792 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
793 | |
794 if (have_video) | |
795 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
796 | |
797 // Run until more data is requested a number of times equal to the number of | |
798 // media types configured. Since prefetching may be in progress, we cannot | |
799 // reliably expect Run() to complete until we have sent demuxer data for all | |
800 // configured media types, above. | |
801 WaitForDecodeDone(have_audio, have_video); | |
802 | |
803 // Simulate seek while decoding EOS or non-EOS for the appropriate | |
804 // stream(s). | |
805 if (have_audio) { | |
806 if (eos_audio) | |
807 player_.OnDemuxerDataAvailable(CreateEOSAck(true)); | |
808 else | |
809 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(1)); | |
810 } | |
811 | |
812 if (have_video) { | |
813 if (eos_video) | |
814 player_.OnDemuxerDataAvailable(CreateEOSAck(false)); | |
815 else | |
816 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
817 } | |
818 | |
819 player_.SeekTo(base::TimeDelta()); | |
820 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
821 WaitForDecodeDone(have_audio, have_video); | |
822 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
823 | |
824 player_.OnDemuxerSeekDone(kNoTimestamp); | |
825 EXPECT_FALSE(manager_.playback_completed()); | |
826 } | |
827 | |
828 base::TimeTicks StartTimeTicks() { | |
829 return player_.start_time_ticks_; | |
830 } | |
831 | |
832 bool IsRequestingDemuxerData(bool is_audio) { | |
833 return GetMediaDecoderJob(is_audio)->is_requesting_demuxer_data_; | |
834 } | |
835 | |
836 bool IsDrainingDecoder(bool is_audio) { | |
837 return GetMediaDecoderJob(is_audio)->drain_decoder_; | |
838 } | |
839 | |
840 protected: | |
841 base::MessageLoop message_loop_; | |
842 MockMediaPlayerManager manager_; | |
843 MockDemuxerAndroid* demuxer_; // Owned by |player_|. | |
844 MediaSourcePlayer player_; | |
845 | |
846 // Track whether a possibly async decoder callback test hook has run. | |
847 bool decoder_callback_hook_executed_; | |
848 | |
849 // We need to keep the surface texture while the decoder is actively decoding. | |
850 // Otherwise, it may trigger unexpected crashes on some devices. To switch | |
851 // surfaces, tests need to create a new surface texture without releasing | |
852 // their previous one. In CreateNextTextureAndSetVideoSurface(), we toggle | |
853 // between two surface textures, only replacing the N-2 texture. Assumption is | |
854 // that no more than N-1 texture is in use by decoder when | |
855 // CreateNextTextureAndSetVideoSurface() is called. | |
856 scoped_refptr<gl::SurfaceTexture> surface_texture_a_; | |
857 scoped_refptr<gl::SurfaceTexture> surface_texture_b_; | |
858 bool surface_texture_a_is_next_; | |
859 int next_texture_id_; | |
860 | |
861 DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayerTest); | |
862 }; | |
863 | |
864 TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithValidConfig) { | |
865 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
866 | |
867 // Test audio codec will be created when valid configs and data are passed to | |
868 // the audio decoder job. | |
869 StartAudioDecoderJob(); | |
870 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
871 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
872 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
873 } | |
874 | |
875 TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithInvalidConfig) { | |
876 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
877 | |
878 // Test audio decoder job will not be created when failed to start the codec. | |
879 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); | |
880 // Replace with invalid |audio_extra_data| | |
881 configs.audio_extra_data.clear(); | |
882 uint8_t invalid_codec_data[] = {0x00, 0xff, 0xff, 0xff, 0xff}; | |
883 configs.audio_extra_data.insert(configs.audio_extra_data.begin(), | |
884 invalid_codec_data, invalid_codec_data + 4); | |
885 Start(configs); | |
886 | |
887 // Decoder is not created after data is received. | |
888 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
889 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
890 } | |
891 | |
892 TEST_F(MediaSourcePlayerTest, StartVideoCodecWithValidSurface) { | |
893 // crbug.com/604602 and crbug.com/597836 | |
894 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
895 | |
896 // Test video codec will not be created until data is received. | |
897 StartVideoDecoderJob(); | |
898 | |
899 // Set both an initial and a later video surface without receiving any | |
900 // demuxed data yet. | |
901 CreateNextTextureAndSetVideoSurface(); | |
902 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
903 CreateNextTextureAndSetVideoSurface(); | |
904 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
905 | |
906 // No seeks, even on setting surface, should have occurred. (Browser seeks can | |
907 // occur on setting surface, but only after previously receiving video data.) | |
908 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
909 | |
910 // Send the first input chunk and verify that decoder will be created. | |
911 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
912 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
913 WaitForVideoDecodeDone(); | |
914 } | |
915 | |
916 TEST_F(MediaSourcePlayerTest, StartVideoCodecWithInvalidSurface) { | |
917 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
918 | |
919 // Test video codec will not be created when surface is invalid. | |
920 scoped_refptr<gl::SurfaceTexture> surface_texture( | |
921 gl::SurfaceTexture::Create(0)); | |
922 gl::ScopedJavaSurface surface(surface_texture.get()); | |
923 StartVideoDecoderJob(); | |
924 | |
925 // Release the surface texture. | |
926 surface_texture = NULL; | |
927 player_.SetVideoSurface(std::move(surface)); | |
928 | |
929 // Player should not seek the demuxer on setting initial surface. | |
930 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
931 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
932 | |
933 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
934 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
935 } | |
936 | |
937 TEST_F(MediaSourcePlayerTest, ReadFromDemuxerAfterSeek) { | |
938 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
939 | |
940 // Test decoder job will resend a ReadFromDemuxer request after seek. | |
941 StartAudioDecoderJob(); | |
942 SeekPlayerWithAbort(true, base::TimeDelta()); | |
943 } | |
944 | |
945 TEST_F(MediaSourcePlayerTest, SetSurfaceWhileSeeking) { | |
946 // crbug.com/604602 and crbug.com/597836 | |
947 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
948 | |
949 // Test SetVideoSurface() will not cause an extra seek while the player is | |
950 // waiting for demuxer to indicate seek is done. | |
951 player_.OnDemuxerConfigsAvailable( | |
952 CreateVideoDemuxerConfigs(false)); | |
953 | |
954 // Initiate a seek. Skip requesting element seek of renderer. | |
955 // Instead behave as if the renderer has asked us to seek. | |
956 player_.SeekTo(base::TimeDelta()); | |
957 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
958 | |
959 CreateNextTextureAndSetVideoSurface(); | |
960 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
961 player_.Start(); | |
962 | |
963 // Send the seek done notification. The player should start requesting data. | |
964 player_.OnDemuxerSeekDone(kNoTimestamp); | |
965 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
966 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
967 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
968 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
969 | |
970 // Reconfirm exactly 1 seek request has been made of demuxer, and that it | |
971 // was not a browser seek request. | |
972 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
973 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
974 WaitForVideoDecodeDone(); | |
975 } | |
976 | |
977 TEST_F(MediaSourcePlayerTest, ChangeMultipleSurfaceWhileDecoding) { | |
978 // crbug.com/604602 and crbug.com/597836 | |
979 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
980 | |
981 // Test MediaSourcePlayer can switch multiple surfaces during decoding. | |
982 CreateNextTextureAndSetVideoSurface(); | |
983 StartVideoDecoderJob(); | |
984 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
985 | |
986 // Send the first input chunk. | |
987 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
988 | |
989 // While the decoder is decoding, change multiple surfaces. Pass an empty | |
990 // surface first. | |
991 gl::ScopedJavaSurface empty_surface; | |
992 player_.SetVideoSurface(std::move(empty_surface)); | |
993 // Next, pass a new non-empty surface. | |
994 CreateNextTextureAndSetVideoSurface(); | |
995 | |
996 // Wait for the media codec bridge to finish decoding and be reset pending a | |
997 // browser seek. | |
998 WaitForVideoDecodeDone(); | |
999 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1000 | |
1001 // Only one browser seek should have been initiated. No further data request | |
1002 // should have been processed on |message_loop_| before surface change event | |
1003 // became pending, above. | |
1004 EXPECT_EQ(1, demuxer_->num_browser_seek_requests()); | |
1005 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
1006 | |
1007 // Simulate browser seek is done and confirm player requests more data for new | |
1008 // video codec. | |
1009 player_.OnDemuxerSeekDone(player_.GetCurrentTime()); | |
1010 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
1011 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1012 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1013 | |
1014 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1015 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1016 WaitForVideoDecodeDone(); | |
1017 } | |
1018 | |
1019 TEST_F(MediaSourcePlayerTest, SetEmptySurfaceAndStarveWhileDecoding) { | |
1020 // crbug.com/604602 and crbug.com/597836 | |
1021 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1022 | |
1023 // Test player pauses if an empty surface is passed. | |
1024 CreateNextTextureAndSetVideoSurface(); | |
1025 StartVideoDecoderJob(); | |
1026 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1027 | |
1028 // Send the first input chunk. | |
1029 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1030 | |
1031 // While the decoder is decoding, pass an empty surface. | |
1032 gl::ScopedJavaSurface empty_surface; | |
1033 player_.SetVideoSurface(std::move(empty_surface)); | |
1034 // Let the player starve. However, it should not issue any new data request in | |
1035 // this case. | |
1036 TriggerPlayerStarvation(); | |
1037 // Wait for the media codec bridge to finish decoding and be reset. | |
1038 while (GetMediaDecoderJob(false)->is_decoding()) | |
1039 base::RunLoop().RunUntilIdle(); | |
1040 | |
1041 // No further seek or data requests should have been received since the | |
1042 // surface is empty. | |
1043 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
1044 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
1045 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1046 | |
1047 // Playback resumes once a non-empty surface is passed. | |
1048 CreateNextTextureAndSetVideoSurface(); | |
1049 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
1050 while(demuxer_->num_browser_seek_requests() != 1) | |
1051 base::RunLoop().RunUntilIdle(); | |
1052 WaitForVideoDecodeDone(); | |
1053 } | |
1054 | |
1055 TEST_F(MediaSourcePlayerTest, ReleaseVideoDecoderResourcesWhileDecoding) { | |
1056 // crbug.com/604602 and crbug.com/597836 | |
1057 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1058 | |
1059 // Test that if video decoder is released while decoding, the resources will | |
1060 // not be immediately released. | |
1061 CreateNextTextureAndSetVideoSurface(); | |
1062 StartVideoDecoderJob(); | |
1063 ReleasePlayer(); | |
1064 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1065 | |
1066 // Recreate the video decoder. | |
1067 CreateNextTextureAndSetVideoSurface(); | |
1068 player_.Start(); | |
1069 while (!GetMediaDecoderJob(false)->is_decoding()) | |
1070 base::RunLoop().RunUntilIdle(); | |
1071 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
1072 ReleasePlayer(); | |
1073 // Wait for the media codec bridge to finish decoding and be reset. | |
1074 while (GetMediaDecoderJob(false)->is_decoding()) | |
1075 base::RunLoop().RunUntilIdle(); | |
1076 } | |
1077 | |
1078 TEST_F(MediaSourcePlayerTest, AudioOnlyStartAfterSeekFinish) { | |
1079 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1080 | |
1081 // Test audio decoder job will not start until pending seek event is handled. | |
1082 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); | |
1083 player_.OnDemuxerConfigsAvailable(configs); | |
1084 | |
1085 // Initiate a seek. Skip requesting element seek of renderer. | |
1086 // Instead behave as if the renderer has asked us to seek. | |
1087 player_.SeekTo(base::TimeDelta()); | |
1088 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1089 | |
1090 player_.Start(); | |
1091 EXPECT_EQ(0, demuxer_->num_data_requests()); | |
1092 | |
1093 // Sending back the seek done notification. | |
1094 player_.OnDemuxerSeekDone(kNoTimestamp); | |
1095 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
1096 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1097 | |
1098 // Reconfirm exactly 1 seek request has been made of demuxer. | |
1099 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1100 | |
1101 // Decoder is created after data is received. | |
1102 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1103 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
1104 } | |
1105 | |
1106 TEST_F(MediaSourcePlayerTest, VideoOnlyStartAfterSeekFinish) { | |
1107 // crbug.com/604602 and crbug.com/597836 | |
1108 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1109 | |
1110 // Test video decoder job will not start until pending seek event is handled. | |
1111 CreateNextTextureAndSetVideoSurface(); | |
1112 DemuxerConfigs configs = CreateVideoDemuxerConfigs(false); | |
1113 player_.OnDemuxerConfigsAvailable(configs); | |
1114 | |
1115 // Initiate a seek. Skip requesting element seek of renderer. | |
1116 // Instead behave as if the renderer has asked us to seek. | |
1117 player_.SeekTo(base::TimeDelta()); | |
1118 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1119 | |
1120 player_.Start(); | |
1121 EXPECT_EQ(0, demuxer_->num_data_requests()); | |
1122 | |
1123 // Sending back the seek done notification. | |
1124 player_.OnDemuxerSeekDone(kNoTimestamp); | |
1125 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
1126 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1127 | |
1128 // Reconfirm exactly 1 seek request has been made of demuxer. | |
1129 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1130 | |
1131 // Decoder is created after data is received. | |
1132 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1133 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1134 WaitForVideoDecodeDone(); | |
1135 } | |
1136 | |
1137 TEST_F(MediaSourcePlayerTest, StartImmediatelyAfterPause) { | |
1138 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1139 | |
1140 // Test that if the decoding job is not fully stopped after Pause(), | |
1141 // calling Start() will be a noop. | |
1142 StartAudioDecoderJob(); | |
1143 | |
1144 MediaDecoderJob* decoder_job = GetMediaDecoderJob(true); | |
1145 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
1146 | |
1147 // Sending data to player. | |
1148 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1149 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1150 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
1151 | |
1152 // Decoder job will not immediately stop after Pause() since it is | |
1153 // running on another thread. | |
1154 player_.Pause(true); | |
1155 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1156 | |
1157 // Nothing happens when calling Start() again. | |
1158 player_.Start(); | |
1159 // Verify that Start() will not destroy and recreate the media codec bridge. | |
1160 EXPECT_EQ(decoder_job, GetMediaDecoderJob(true)); | |
1161 | |
1162 while (GetMediaDecoderJob(true)->is_decoding()) | |
1163 base::RunLoop().RunUntilIdle(); | |
1164 // The decoder job should finish and wait for data. | |
1165 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
1166 EXPECT_TRUE(IsRequestingDemuxerData(true)); | |
1167 } | |
1168 | |
1169 TEST_F(MediaSourcePlayerTest, DecoderJobsCannotStartWithoutAudio) { | |
1170 // crbug.com/604602 and crbug.com/597836 | |
1171 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1172 | |
1173 // Test that when Start() is called, video decoder job will wait for audio | |
1174 // decoder job before start decoding the data. | |
1175 CreateNextTextureAndSetVideoSurface(); | |
1176 Start(CreateAudioVideoDemuxerConfigs()); | |
1177 MediaDecoderJob* audio_decoder_job = GetMediaDecoderJob(true); | |
1178 MediaDecoderJob* video_decoder_job = GetMediaDecoderJob(false); | |
1179 | |
1180 EXPECT_FALSE(audio_decoder_job->is_decoding()); | |
1181 EXPECT_FALSE(video_decoder_job->is_decoding()); | |
1182 | |
1183 // Sending video data to player, video decoder should not start. | |
1184 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1185 EXPECT_FALSE(video_decoder_job->is_decoding()); | |
1186 | |
1187 // Sending audio data to player, both decoders should start now. | |
1188 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1189 EXPECT_TRUE(audio_decoder_job->is_decoding()); | |
1190 EXPECT_TRUE(video_decoder_job->is_decoding()); | |
1191 | |
1192 // No seeks should have occurred. | |
1193 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
1194 WaitForVideoDecodeDone(); | |
1195 } | |
1196 | |
1197 TEST_F(MediaSourcePlayerTest, StartTimeTicksResetAfterDecoderUnderruns) { | |
1198 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1199 | |
1200 // Test start time ticks will reset after decoder job underruns. | |
1201 StartAudioDecoderJob(); | |
1202 | |
1203 DecodeAudioDataUntilOutputBecomesAvailable(); | |
1204 | |
1205 // The decoder job should finish prerolling and start prefetching. | |
1206 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); | |
1207 base::TimeTicks previous = StartTimeTicks(); | |
1208 | |
1209 // Let the decoder starve. | |
1210 TriggerPlayerStarvation(); | |
1211 WaitForAudioDecodeDone(); | |
1212 EXPECT_TRUE(StartTimeTicks() == previous); | |
1213 | |
1214 // Send new data to the decoder so it can finish prefetching. This should | |
1215 // reset the start time ticks. | |
1216 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); | |
1217 EXPECT_TRUE(StartTimeTicks() != previous); | |
1218 | |
1219 base::TimeTicks current = StartTimeTicks(); | |
1220 EXPECT_LE(0, (current - previous).InMillisecondsF()); | |
1221 } | |
1222 | |
1223 TEST_F(MediaSourcePlayerTest, V_SecondAccessUnitIsEOSAndResumePlayAfterSeek) { | |
1224 // crbug.com/604602 and crbug.com/597836 | |
1225 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1226 | |
1227 // Test MediaSourcePlayer can replay video after input EOS is reached. | |
1228 CreateNextTextureAndSetVideoSurface(); | |
1229 StartVideoDecoderJob(); | |
1230 | |
1231 // Send the first input chunk. | |
1232 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1233 WaitForVideoDecodeDone(); | |
1234 | |
1235 VerifyPlaybackCompletesOnEOSDecode(true, false); | |
1236 VerifyCompletedPlaybackResumesOnSeekPlusStart(false, true); | |
1237 } | |
1238 | |
1239 TEST_F(MediaSourcePlayerTest, A_FirstAccessUnitIsEOSAndResumePlayAfterSeek) { | |
1240 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1241 | |
1242 // Test decode of audio EOS buffer without any prior decode. See also | |
1243 // http://b/11696552. | |
1244 // Also tests that seeking+Start() after completing audio playback resumes | |
1245 // playback. | |
1246 Start(CreateAudioDemuxerConfigs(kCodecAAC, false)); | |
1247 VerifyPlaybackCompletesOnEOSDecode(true, true); | |
1248 VerifyCompletedPlaybackResumesOnSeekPlusStart(true, false); | |
1249 } | |
1250 | |
1251 TEST_F(MediaSourcePlayerTest, V_FirstAccessUnitAfterSeekIsEOS) { | |
1252 // crbug.com/604602 and crbug.com/597836 | |
1253 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1254 | |
1255 // Test decode of video EOS buffer, just after seeking, without any prior | |
1256 // decode (other than the simulated |kAborted| resulting from the seek | |
1257 // process.) | |
1258 CreateNextTextureAndSetVideoSurface(); | |
1259 StartVideoDecoderJob(); | |
1260 SeekPlayerWithAbort(false, base::TimeDelta()); | |
1261 VerifyPlaybackCompletesOnEOSDecode(true, false); | |
1262 } | |
1263 | |
1264 TEST_F(MediaSourcePlayerTest, A_FirstAccessUnitAfterSeekIsEOS) { | |
1265 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1266 | |
1267 // Test decode of audio EOS buffer, just after seeking, without any prior | |
1268 // decode (other than the simulated |kAborted| resulting from the seek | |
1269 // process.) See also http://b/11696552. | |
1270 Start(CreateAudioDemuxerConfigs(kCodecAAC, false)); | |
1271 SeekPlayerWithAbort(true, base::TimeDelta()); | |
1272 VerifyPlaybackCompletesOnEOSDecode(true, true); | |
1273 } | |
1274 | |
1275 TEST_F(MediaSourcePlayerTest, AV_PlaybackCompletionAcrossConfigChange) { | |
1276 // crbug.com/604602 and crbug.com/597836 | |
1277 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1278 | |
1279 // Test that if one stream (audio) has completed decode of EOS and the other | |
1280 // stream (video) processes config change, that subsequent video EOS completes | |
1281 // A/V playback. | |
1282 // Also tests that seeking+Start() after completing playback resumes playback. | |
1283 CreateNextTextureAndSetVideoSurface(); | |
1284 Start(CreateAudioVideoDemuxerConfigs()); | |
1285 | |
1286 player_.OnDemuxerDataAvailable(CreateEOSAck(true)); // Audio EOS | |
1287 DemuxerConfigs configs = CreateVideoDemuxerConfigs(true); | |
1288 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckWithConfigChanged( | |
1289 false, 0, configs)); // Video |kConfigChanged| as first unit. | |
1290 | |
1291 WaitForAudioVideoDecodeDone(); | |
1292 | |
1293 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1294 | |
1295 // At no time after completing audio EOS decode, above, should the | |
1296 // audio decoder job resume decoding. Send and decode video EOS. | |
1297 VerifyPlaybackCompletesOnEOSDecode(true, false); | |
1298 VerifyCompletedPlaybackResumesOnSeekPlusStart(true, true); | |
1299 } | |
1300 | |
1301 TEST_F(MediaSourcePlayerTest, VA_PlaybackCompletionAcrossConfigChange) { | |
1302 // crbug.com/604602 and crbug.com/597836 | |
1303 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1304 | |
1305 // Test that if one stream (video) has completed decode of EOS and the other | |
1306 // stream (audio) processes config change, that subsequent audio EOS completes | |
1307 // A/V playback. | |
1308 // Also tests that seeking+Start() after completing playback resumes playback. | |
1309 CreateNextTextureAndSetVideoSurface(); | |
1310 Start(CreateAudioVideoDemuxerConfigs()); | |
1311 | |
1312 player_.OnDemuxerDataAvailable(CreateEOSAck(false)); // Video EOS | |
1313 // Audio |kConfigChanged| as first unit. | |
1314 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckWithConfigChanged( | |
1315 true, 0, CreateAudioDemuxerConfigs(kCodecVorbis, false))); | |
1316 | |
1317 WaitForAudioVideoDecodeDone(); | |
1318 | |
1319 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1320 | |
1321 // At no time after completing video EOS decode, above, should the | |
1322 // video decoder job resume decoding. Send and decode audio EOS. | |
1323 VerifyPlaybackCompletesOnEOSDecode(true, true); | |
1324 VerifyCompletedPlaybackResumesOnSeekPlusStart(true, true); | |
1325 } | |
1326 | |
1327 TEST_F(MediaSourcePlayerTest, AV_NoPrefetchForFinishedVideoOnAudioStarvation) { | |
1328 // crbug.com/604602 and crbug.com/597836 | |
1329 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1330 | |
1331 // Test that if one stream (video) has completed decode of EOS, prefetch | |
1332 // resulting from player starvation occurs only for the other stream (audio), | |
1333 // and responding to that prefetch with EOS completes A/V playback, even if | |
1334 // another starvation occurs during the latter EOS's decode. | |
1335 CreateNextTextureAndSetVideoSurface(); | |
1336 Start(CreateAudioVideoDemuxerConfigs()); | |
1337 | |
1338 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1339 player_.OnDemuxerDataAvailable(CreateEOSAck(false)); // Video EOS | |
1340 | |
1341 // Wait until video EOS is processed and more data (assumed to be audio) is | |
1342 // requested. | |
1343 WaitForAudioVideoDecodeDone(); | |
1344 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1345 | |
1346 // Simulate decoder underrun to trigger prefetch while still decoding audio. | |
1347 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(1)); | |
1348 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding() && | |
1349 !GetMediaDecoderJob(false)->is_decoding()); | |
1350 TriggerPlayerStarvation(); | |
1351 | |
1352 // Complete the audio decode that was in progress when simulated player | |
1353 // starvation was triggered. | |
1354 WaitForAudioDecodeDone(); | |
1355 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
1356 player_.OnDemuxerDataAvailable(CreateEOSAck(true)); // Audio EOS | |
1357 EXPECT_FALSE(GetMediaDecoderJob(false)->is_decoding()); | |
1358 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1359 | |
1360 // Simulate another decoder underrun to trigger prefetch while decoding EOS. | |
1361 TriggerPlayerStarvation(); | |
1362 VerifyPlaybackCompletesOnEOSDecode(false, true /* ignored */); | |
1363 } | |
1364 | |
1365 TEST_F(MediaSourcePlayerTest, V_StarvationDuringEOSDecode) { | |
1366 // crbug.com/604602 and crbug.com/597836 | |
1367 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1368 | |
1369 // Test that video-only playback completes without further data requested when | |
1370 // starvation occurs during EOS decode. | |
1371 CreateNextTextureAndSetVideoSurface(); | |
1372 StartVideoDecoderJob(); | |
1373 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1374 WaitForVideoDecodeDone(); | |
1375 | |
1376 // Simulate decoder underrun to trigger prefetch while decoding EOS. | |
1377 player_.OnDemuxerDataAvailable(CreateEOSAck(false)); // Video EOS | |
1378 EXPECT_TRUE(GetMediaDecoderJob(false)->is_decoding()); | |
1379 TriggerPlayerStarvation(); | |
1380 VerifyPlaybackCompletesOnEOSDecode(false, false /* ignored */); | |
1381 } | |
1382 | |
1383 TEST_F(MediaSourcePlayerTest, A_StarvationDuringEOSDecode) { | |
1384 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1385 | |
1386 // Test that audio-only playback completes without further data requested when | |
1387 // starvation occurs during EOS decode. | |
1388 StartAudioDecoderJob(); | |
1389 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1390 WaitForAudioDecodeDone(); | |
1391 | |
1392 // Simulate decoder underrun to trigger prefetch while decoding EOS. | |
1393 player_.OnDemuxerDataAvailable(CreateEOSAck(true)); // Audio EOS | |
1394 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1395 TriggerPlayerStarvation(); | |
1396 VerifyPlaybackCompletesOnEOSDecode(false, true /* ignored */); | |
1397 } | |
1398 | |
1399 TEST_F(MediaSourcePlayerTest, AV_SeekDuringEOSDecodePreventsCompletion) { | |
1400 // crbug.com/604602 and crbug.com/597836 | |
1401 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1402 | |
1403 // Test that seek supercedes audio+video playback completion on simultaneous | |
1404 // audio and video EOS decode, if SeekTo() occurs during these EOS decodes. | |
1405 VerifySeekDuringEOSDecodePreventsPlaybackCompletion(true, true, true, true); | |
1406 } | |
1407 | |
1408 TEST_F(MediaSourcePlayerTest, AV_SeekDuringAudioEOSDecodePreventsCompletion) { | |
1409 // crbug.com/604602 and crbug.com/597836 | |
1410 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1411 | |
1412 // Test that seek supercedes audio+video playback completion on simultaneous | |
1413 // audio EOS and video non-EOS decode, if SeekTo() occurs during these | |
1414 // decodes. | |
1415 VerifySeekDuringEOSDecodePreventsPlaybackCompletion(true, true, true, false); | |
1416 } | |
1417 | |
1418 TEST_F(MediaSourcePlayerTest, AV_SeekDuringVideoEOSDecodePreventsCompletion) { | |
1419 // crbug.com/604602 and crbug.com/597836 | |
1420 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1421 | |
1422 // Test that seek supercedes audio+video playback completion on simultaneous | |
1423 // audio non-EOS and video EOS decode, if SeekTo() occurs during these | |
1424 // decodes. | |
1425 VerifySeekDuringEOSDecodePreventsPlaybackCompletion(true, true, false, true); | |
1426 } | |
1427 | |
1428 TEST_F(MediaSourcePlayerTest, V_SeekDuringEOSDecodePreventsCompletion) { | |
1429 // crbug.com/604602 and crbug.com/597836 | |
1430 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1431 | |
1432 // Test that seek supercedes video-only playback completion on EOS decode, if | |
1433 // SeekTo() occurs during EOS decode. | |
1434 VerifySeekDuringEOSDecodePreventsPlaybackCompletion(false, true, false, true); | |
1435 } | |
1436 | |
1437 TEST_F(MediaSourcePlayerTest, A_SeekDuringEOSDecodePreventsCompletion) { | |
1438 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1439 | |
1440 // Test that seek supercedes audio-only playback completion on EOS decode, if | |
1441 // SeekTo() occurs during EOS decode. | |
1442 VerifySeekDuringEOSDecodePreventsPlaybackCompletion(true, false, true, false); | |
1443 } | |
1444 | |
1445 TEST_F(MediaSourcePlayerTest, NoRequestForDataAfterAbort) { | |
1446 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1447 | |
1448 // Test that the decoder will not request new data after receiving an aborted | |
1449 // access unit. | |
1450 StartAudioDecoderJob(); | |
1451 | |
1452 // Send an aborted access unit. | |
1453 player_.OnDemuxerDataAvailable(CreateAbortedAck(true)); | |
1454 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1455 WaitForAudioDecodeDone(); | |
1456 | |
1457 // No request will be sent for new data. | |
1458 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1459 | |
1460 // No seek requests should have occurred. | |
1461 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
1462 } | |
1463 | |
1464 TEST_F(MediaSourcePlayerTest, DemuxerDataArrivesAfterRelease) { | |
1465 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1466 | |
1467 // Test that the decoder should not crash if demuxer data arrives after | |
1468 // Release(). | |
1469 StartAudioDecoderJob(); | |
1470 | |
1471 ReleasePlayer(); | |
1472 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1473 | |
1474 // The media codec bridge should have been released. | |
1475 EXPECT_FALSE(player_.IsPlaying()); | |
1476 | |
1477 // No further data should have been requested. | |
1478 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1479 | |
1480 // No seek requests should have occurred. | |
1481 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
1482 } | |
1483 | |
1484 TEST_F(MediaSourcePlayerTest, BrowserSeek_RegularSeekPendsBrowserSeekDone) { | |
1485 // crbug.com/604602 and crbug.com/597836 | |
1486 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1487 | |
1488 // Test that a browser seek, once started, delays a newly arrived regular | |
1489 // SeekTo() request's demuxer seek until the browser seek is done. | |
1490 BrowserSeekPlayer(false); | |
1491 | |
1492 // Simulate renderer requesting a regular seek while browser seek in progress. | |
1493 player_.SeekTo(base::TimeDelta()); | |
1494 | |
1495 // Simulate browser seek is done. Confirm player requests the regular seek, | |
1496 // still has no video codec configured, and has not requested any | |
1497 // further data since the surface change event became pending in | |
1498 // BrowserSeekPlayer(). | |
1499 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1500 player_.OnDemuxerSeekDone(base::TimeDelta()); | |
1501 EXPECT_EQ(2, demuxer_->num_seek_requests()); | |
1502 EXPECT_EQ(1, demuxer_->num_browser_seek_requests()); | |
1503 | |
1504 // Simulate regular seek is done and confirm player requests more data for | |
1505 // new video codec. | |
1506 player_.OnDemuxerSeekDone(kNoTimestamp); | |
1507 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
1508 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1509 EXPECT_EQ(2, demuxer_->num_seek_requests()); | |
1510 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1511 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1512 WaitForVideoDecodeDone(); | |
1513 } | |
1514 | |
1515 TEST_F(MediaSourcePlayerTest, BrowserSeek_InitialReleaseAndStart) { | |
1516 // crbug.com/604602 and crbug.com/597836 | |
1517 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1518 | |
1519 // Test that no browser seek is requested if player Release() + Start() occurs | |
1520 // prior to receiving any data. | |
1521 CreateNextTextureAndSetVideoSurface(); | |
1522 StartVideoDecoderJob(); | |
1523 ReleasePlayer(); | |
1524 | |
1525 // Pass a new non-empty surface. | |
1526 CreateNextTextureAndSetVideoSurface(); | |
1527 | |
1528 player_.Start(); | |
1529 | |
1530 // No data request is issued since there is still one pending. | |
1531 EXPECT_EQ(1, demuxer_->num_data_requests()); | |
1532 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
1533 | |
1534 // No browser seek is needed. | |
1535 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1536 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
1537 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
1538 WaitForVideoDecodeDone(); | |
1539 } | |
1540 | |
1541 TEST_F(MediaSourcePlayerTest, BrowserSeek_MidStreamReleaseAndStart) { | |
1542 // crbug.com/604602 and crbug.com/597836 | |
1543 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1544 | |
1545 // Test that one browser seek is requested if player Release() + Start(), with | |
1546 // video data received between Release() and Start(). | |
1547 BrowserSeekPlayer(true); | |
1548 | |
1549 // Simulate browser seek is done and confirm player requests more data. | |
1550 player_.OnDemuxerSeekDone(base::TimeDelta()); | |
1551 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1552 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1553 } | |
1554 | |
1555 TEST_F(MediaSourcePlayerTest, NoBrowserSeekWithKeyFrameInCache) { | |
1556 // crbug.com/604602 and crbug.com/597836 | |
1557 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1558 | |
1559 // Test that browser seek is not needed if a key frame is found in data | |
1560 // cache. | |
1561 CreateNextTextureAndSetVideoSurface(); | |
1562 StartVideoDecoderJob(); | |
1563 DemuxerData data = CreateReadFromDemuxerAckForVideo(false); | |
1564 data.access_units[0].is_key_frame = true; | |
1565 | |
1566 // Simulate demuxer's response to the video data request. | |
1567 player_.OnDemuxerDataAvailable(data); | |
1568 | |
1569 // Trigger decoder recreation later by changing surfaces. | |
1570 CreateNextTextureAndSetVideoSurface(); | |
1571 | |
1572 // Wait for the media codec bridge to finish decoding and be reset. | |
1573 WaitForVideoDecodeDone(); | |
1574 EXPECT_FALSE(HasData(false)); | |
1575 | |
1576 // Send a non key frame to decoder so that decoder can continue. This will | |
1577 // not trigger any browser seeks as the previous key frame is still in the | |
1578 // buffer. | |
1579 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1580 WaitForVideoDecodeDone(); | |
1581 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
1582 } | |
1583 | |
1584 TEST_F(MediaSourcePlayerTest, PrerollAudioAfterSeek) { | |
1585 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1586 | |
1587 // Test decoder job will preroll the media to the seek position. | |
1588 StartAudioDecoderJob(); | |
1589 | |
1590 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); | |
1591 EXPECT_TRUE(IsPrerolling(true)); | |
1592 PrerollDecoderToTime( | |
1593 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100), true); | |
1594 } | |
1595 | |
1596 TEST_F(MediaSourcePlayerTest, PrerollVideoAfterSeek) { | |
1597 // crbug.com/604602 and crbug.com/597836 | |
1598 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1599 | |
1600 // Test decoder job will preroll the media to the seek position. | |
1601 CreateNextTextureAndSetVideoSurface(); | |
1602 StartVideoDecoderJob(); | |
1603 | |
1604 SeekPlayerWithAbort(false, base::TimeDelta::FromMilliseconds(100)); | |
1605 EXPECT_TRUE(IsPrerolling(false)); | |
1606 PrerollDecoderToTime( | |
1607 false, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100), true); | |
1608 } | |
1609 | |
1610 TEST_F(MediaSourcePlayerTest, SeekingAfterCompletingPrerollRestartsPreroll) { | |
1611 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1612 | |
1613 // Test decoder job will begin prerolling upon seek, when it was not | |
1614 // prerolling prior to the seek. | |
1615 StartAudioDecoderJob(); | |
1616 MediaDecoderJob* decoder_job = GetMediaDecoderJob(true); | |
1617 EXPECT_TRUE(IsPrerolling(true)); | |
1618 | |
1619 // Complete the initial preroll by feeding data to the decoder. | |
1620 DecodeAudioDataUntilOutputBecomesAvailable(); | |
1621 EXPECT_FALSE(IsPrerolling(true)); | |
1622 | |
1623 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(500)); | |
1624 | |
1625 // Prerolling should have begun again. | |
1626 EXPECT_TRUE(IsPrerolling(true)); | |
1627 EXPECT_EQ(500.0, GetPrerollTimestamp().InMillisecondsF()); | |
1628 | |
1629 // Send data at and after the seek position. Prerolling should complete. | |
1630 for (int i = 0; i < 4; ++i) { | |
1631 DemuxerData data = CreateReadFromDemuxerAckForAudio(i); | |
1632 data.access_units[0].timestamp = base::TimeDelta::FromMilliseconds( | |
1633 500 + 30 * (i - 1)); | |
1634 player_.OnDemuxerDataAvailable(data); | |
1635 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1636 WaitForAudioDecodeDone(); | |
1637 } | |
1638 EXPECT_LT(500.0, player_.GetCurrentTime().InMillisecondsF()); | |
1639 EXPECT_FALSE(IsPrerolling(true)); | |
1640 | |
1641 // Throughout this test, we should have not re-created the media codec bridge, | |
1642 // so IsPrerolling() transition from false to true was not due to constructor | |
1643 // initialization. It was due to BeginPrerolling(). | |
1644 EXPECT_EQ(decoder_job, GetMediaDecoderJob(true)); | |
1645 } | |
1646 | |
1647 TEST_F(MediaSourcePlayerTest, PrerollContinuesAcrossReleaseAndStart) { | |
1648 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1649 | |
1650 // Test decoder job will resume media prerolling if interrupted by Release() | |
1651 // and Start(). | |
1652 StartAudioDecoderJob(); | |
1653 | |
1654 base::TimeDelta target_timestamp = base::TimeDelta::FromMilliseconds(100); | |
1655 SeekPlayerWithAbort(true, target_timestamp); | |
1656 EXPECT_TRUE(IsPrerolling(true)); | |
1657 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
1658 | |
1659 // Send some data before the seek position. | |
1660 // Test uses 'large' number of iterations because decoder job may not get | |
1661 // MEDIA_CODEC_OK output status until after a few dequeue output attempts. | |
1662 // This allows decoder status to stabilize prior to AU timestamp reaching | |
1663 // the preroll target. | |
1664 DemuxerData data; | |
1665 for (int i = 0; i < 10; ++i) { | |
1666 data = CreateReadFromDemuxerAckForAudio(3); | |
1667 data.access_units[0].timestamp = base::TimeDelta::FromMilliseconds(i * 10); | |
1668 if (i == 1) { | |
1669 // While still prerolling, Release() and Start() the player. | |
1670 ReleasePlayer(); | |
1671 // The decoder is still decoding and will not be immediately released. | |
1672 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
1673 Resume(false, false); | |
1674 } else { | |
1675 player_.OnDemuxerDataAvailable(data); | |
1676 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1677 WaitForAudioDecodeDone(); | |
1678 } | |
1679 EXPECT_TRUE(IsPrerolling(true)); | |
1680 } | |
1681 EXPECT_EQ(100.0, player_.GetCurrentTime().InMillisecondsF()); | |
1682 EXPECT_TRUE(IsPrerolling(true)); | |
1683 | |
1684 // Send data after the seek position. | |
1685 PrerollDecoderToTime(true, target_timestamp, target_timestamp, true); | |
1686 } | |
1687 | |
1688 // Flaky on Android: crbug.com/419122. | |
1689 #if defined(OS_ANDROID) | |
1690 #define MAYBE_PrerollContinuesAcrossConfigChange \ | |
1691 DISABLED_PrerollContinuesAcrossConfigChange | |
1692 #else | |
1693 #define MAYBE_PrerollContinuesAcrossConfigChange \ | |
1694 PrerollContinuesAcrossConfigChange | |
1695 #endif | |
1696 TEST_F(MediaSourcePlayerTest, MAYBE_PrerollContinuesAcrossConfigChange) { | |
1697 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1698 | |
1699 // Test decoder job will resume media prerolling if interrupted by | |
1700 // |kConfigChanged| and OnDemuxerConfigsAvailable(). | |
1701 StartAudioDecoderJob(); | |
1702 | |
1703 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); | |
1704 EXPECT_TRUE(IsPrerolling(true)); | |
1705 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
1706 | |
1707 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | |
1708 | |
1709 // In response to data request, simulate that demuxer signals config change by | |
1710 // sending an AU with |kConfigChanged|. | |
1711 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | |
1712 true, 0, configs); | |
1713 player_.OnDemuxerDataAvailable(data); | |
1714 | |
1715 PrerollDecoderToTime( | |
1716 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100), true); | |
1717 } | |
1718 | |
1719 TEST_F(MediaSourcePlayerTest, PrerollContinuesAfterUnchangedConfigs) { | |
1720 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1721 | |
1722 // Test decoder job will resume media prerolling if interrupted by a config | |
1723 // change access unit with unchanged configs. | |
1724 StartAudioDecoderJob(); | |
1725 | |
1726 SeekPlayerWithAbort(true, base::TimeDelta::FromMilliseconds(100)); | |
1727 EXPECT_TRUE(IsPrerolling(true)); | |
1728 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
1729 | |
1730 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, false); | |
1731 | |
1732 // In response to data request, simulate that demuxer signals config change by | |
1733 // sending an AU with |kConfigChanged|. | |
1734 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | |
1735 true, 0, configs); | |
1736 player_.OnDemuxerDataAvailable(data); | |
1737 PrerollDecoderToTime( | |
1738 true, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100), true); | |
1739 } | |
1740 | |
1741 TEST_F(MediaSourcePlayerTest, AudioPrerollFinishesBeforeVideo) { | |
1742 // crbug.com/604602 and crbug.com/597836 | |
1743 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1744 | |
1745 // Test that after audio finishes prerolling, it will wait for video to finish | |
1746 // prerolling before advancing together. | |
1747 CreateNextTextureAndSetVideoSurface(); | |
1748 Start(CreateAudioVideoDemuxerConfigs()); | |
1749 | |
1750 // Initiate a seek. | |
1751 base::TimeDelta seek_position = base::TimeDelta::FromMilliseconds(100); | |
1752 player_.SeekTo(seek_position); | |
1753 player_.OnDemuxerDataAvailable(CreateAbortedAck(true)); | |
1754 player_.OnDemuxerDataAvailable(CreateAbortedAck(false)); | |
1755 WaitForDecodeDone(true, true); | |
1756 | |
1757 // Verify that the seek is requested. | |
1758 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1759 player_.OnDemuxerSeekDone(kNoTimestamp); | |
1760 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
1761 EXPECT_EQ(player_.GetCurrentTime().InMillisecondsF(), 100.0); | |
1762 EXPECT_EQ(GetPrerollTimestamp().InMillisecondsF(), 100.0); | |
1763 | |
1764 // Send both audio and video data to finish prefetching. | |
1765 base::TimeDelta seek_ack_position = base::TimeDelta::FromMilliseconds(70); | |
1766 DemuxerData audio_data = CreateReadFromDemuxerAckForAudio(0); | |
1767 audio_data.access_units[0].timestamp = seek_ack_position; | |
1768 DemuxerData video_data = CreateReadFromDemuxerAckForVideo(false); | |
1769 video_data.access_units[0].timestamp = seek_ack_position; | |
1770 player_.OnDemuxerDataAvailable(audio_data); | |
1771 player_.OnDemuxerDataAvailable(video_data); | |
1772 WaitForAudioDecodeDone(); | |
1773 WaitForVideoDecodeDone(); | |
1774 | |
1775 // Send audio data at and after the seek position. Audio should finish | |
1776 // prerolling and stop decoding. | |
1777 EXPECT_EQ(6, demuxer_->num_data_requests()); | |
1778 PrerollDecoderToTime(true, seek_position, seek_position, true); | |
1779 EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding()); | |
1780 EXPECT_FALSE(IsPrerolling(true)); | |
1781 EXPECT_TRUE(IsPrerolling(false)); | |
1782 | |
1783 // Send video data to let video finish prerolling. | |
1784 PrerollDecoderToTime(false, seek_position, seek_position, false); | |
1785 EXPECT_FALSE(IsPrerolling(false)); | |
1786 | |
1787 // Both audio and video decoders should start decoding again. | |
1788 player_.OnDemuxerDataAvailable(audio_data); | |
1789 player_.OnDemuxerDataAvailable(video_data); | |
1790 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
1791 EXPECT_TRUE(GetMediaDecoderJob(false)->is_decoding()); | |
1792 } | |
1793 | |
1794 TEST_F(MediaSourcePlayerTest, SimultaneousAudioVideoConfigChange) { | |
1795 // crbug.com/604602 and crbug.com/597836 | |
1796 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1797 | |
1798 // Test that the player allows simultaneous audio and video config change, | |
1799 // such as might occur during OnPrefetchDone() if next access unit for both | |
1800 // audio and video jobs is |kConfigChanged|. | |
1801 CreateNextTextureAndSetVideoSurface(); | |
1802 Start(CreateAudioVideoDemuxerConfigs()); | |
1803 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1804 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1805 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
1806 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1807 EnableAdaptiveVideoPlayback(false); | |
1808 WaitForAudioVideoDecodeDone(); | |
1809 | |
1810 // If audio or video hasn't finished prerolling, let them finish it. | |
1811 if (IsPrerolling(true)) | |
1812 PrerollDecoderToTime(true, base::TimeDelta(), base::TimeDelta(), true); | |
1813 if (IsPrerolling(false)) | |
1814 PrerollDecoderToTime(false, base::TimeDelta(), base::TimeDelta(), false); | |
1815 int expected_num_data_requests = demuxer_->num_data_requests(); | |
1816 | |
1817 // Simulate audio |kConfigChanged| prefetched as standalone access unit. | |
1818 DemuxerConfigs audio_configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | |
1819 player_.OnDemuxerDataAvailable( | |
1820 CreateReadFromDemuxerAckWithConfigChanged(true, 0, audio_configs)); | |
1821 | |
1822 // Simulate video |kConfigChanged| prefetched as standalone access unit. | |
1823 player_.OnDemuxerDataAvailable( | |
1824 CreateReadFromDemuxerAckWithConfigChanged( | |
1825 false, 0, CreateVideoDemuxerConfigs(true))); | |
1826 EXPECT_EQ(expected_num_data_requests + 2, demuxer_->num_data_requests()); | |
1827 EXPECT_TRUE(IsDrainingDecoder(true)); | |
1828 EXPECT_TRUE(IsDrainingDecoder(false)); | |
1829 | |
1830 // Waiting for decoder to finish draining. | |
1831 while (IsDrainingDecoder(true) || IsDrainingDecoder(false)) | |
1832 base::RunLoop().RunUntilIdle(); | |
1833 } | |
1834 | |
1835 TEST_F(MediaSourcePlayerTest, | |
1836 SimultaneousAudioVideoConfigChangeWithAdaptivePlayback) { | |
1837 // crbug.com/604602 and crbug.com/597836 | |
1838 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1839 | |
1840 // Test that the player allows simultaneous audio and video config change with | |
1841 // adaptive video playback enabled. | |
1842 CreateNextTextureAndSetVideoSurface(); | |
1843 Start(CreateAudioVideoDemuxerConfigs()); | |
1844 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
1845 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
1846 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
1847 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
1848 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1849 EnableAdaptiveVideoPlayback(true); | |
1850 WaitForAudioVideoDecodeDone(); | |
1851 | |
1852 // If audio or video hasn't finished prerolling, let them finish it. | |
1853 if (IsPrerolling(true)) | |
1854 PrerollDecoderToTime(true, base::TimeDelta(), base::TimeDelta(), true); | |
1855 if (IsPrerolling(false)) | |
1856 PrerollDecoderToTime(false, base::TimeDelta(), base::TimeDelta(), false); | |
1857 int expected_num_data_requests = demuxer_->num_data_requests(); | |
1858 | |
1859 // Simulate audio |kConfigChanged| prefetched as standalone access unit. | |
1860 DemuxerConfigs audio_configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | |
1861 player_.OnDemuxerDataAvailable( | |
1862 CreateReadFromDemuxerAckWithConfigChanged(true, 0, audio_configs)); | |
1863 | |
1864 // Simulate video |kConfigChanged| prefetched as standalone access unit. | |
1865 player_.OnDemuxerDataAvailable( | |
1866 CreateReadFromDemuxerAckWithConfigChanged( | |
1867 false, 0, CreateVideoDemuxerConfigs(true))); | |
1868 EXPECT_EQ(expected_num_data_requests + 2, demuxer_->num_data_requests()); | |
1869 EXPECT_TRUE(IsDrainingDecoder(true)); | |
1870 EXPECT_FALSE(IsDrainingDecoder(false)); | |
1871 | |
1872 // Waiting for audio decoder to finish draining. | |
1873 while (IsDrainingDecoder(true)) | |
1874 base::RunLoop().RunUntilIdle(); | |
1875 } | |
1876 | |
1877 TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInPrefetchUnit0) { | |
1878 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1879 | |
1880 // Test that the player detects need for and requests demuxer configs if | |
1881 // the |kConfigChanged| unit is the very first unit in the set of units | |
1882 // received in OnDemuxerDataAvailable() ostensibly while | |
1883 // |PREFETCH_DONE_EVENT_PENDING|. | |
1884 StartConfigChange(true, true, 0, false); | |
1885 WaitForAudioDecodeDone(); | |
1886 } | |
1887 | |
1888 TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInPrefetchUnit1) { | |
1889 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1890 | |
1891 // Test that the player detects need for and requests demuxer configs if | |
1892 // the |kConfigChanged| unit is not the first unit in the set of units | |
1893 // received in OnDemuxerDataAvailable() ostensibly while | |
1894 // |PREFETCH_DONE_EVENT_PENDING|. | |
1895 StartConfigChange(true, true, 1, false); | |
1896 WaitForAudioDecodeDone(); | |
1897 } | |
1898 | |
1899 TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit0AfterPrefetch) { | |
1900 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1901 | |
1902 // Test that the player detects need for and requests demuxer configs if | |
1903 // the |kConfigChanged| unit is the very first unit in the set of units | |
1904 // received in OnDemuxerDataAvailable() from data requested ostensibly while | |
1905 // not prefetching. | |
1906 StartConfigChange(true, false, 0, false); | |
1907 WaitForAudioDecodeDone(); | |
1908 } | |
1909 | |
1910 TEST_F(MediaSourcePlayerTest, DemuxerConfigRequestedIfInUnit1AfterPrefetch) { | |
1911 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1912 | |
1913 // Test that the player detects need for and requests demuxer configs if | |
1914 // the |kConfigChanged| unit is not the first unit in the set of units | |
1915 // received in OnDemuxerDataAvailable() from data requested ostensibly while | |
1916 // not prefetching. | |
1917 StartConfigChange(true, false, 1, false); | |
1918 WaitForAudioDecodeDone(); | |
1919 } | |
1920 | |
1921 TEST_F(MediaSourcePlayerTest, BrowserSeek_PrerollAfterBrowserSeek) { | |
1922 // crbug.com/604602 and crbug.com/597836 | |
1923 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1924 | |
1925 // Test decoder job will preroll the media to the actual seek position | |
1926 // resulting from a browser seek. | |
1927 BrowserSeekPlayer(false); | |
1928 | |
1929 // Simulate browser seek is done, but to a later time than was requested. | |
1930 EXPECT_LT(player_.GetCurrentTime().InMillisecondsF(), 100); | |
1931 player_.OnDemuxerSeekDone(base::TimeDelta::FromMilliseconds(100)); | |
1932 // Because next AU is not I-frame, MediaCodecBridge will not be recreated. | |
1933 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
1934 EXPECT_EQ(100.0, player_.GetCurrentTime().InMillisecondsF()); | |
1935 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
1936 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1937 | |
1938 PrerollDecoderToTime( | |
1939 false, base::TimeDelta(), base::TimeDelta::FromMilliseconds(100), true); | |
1940 } | |
1941 | |
1942 TEST_F(MediaSourcePlayerTest, VideoDemuxerConfigChange) { | |
1943 // crbug.com/604602 and crbug.com/597836 | |
1944 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1945 | |
1946 // Test that video config change notification results in creating a new | |
1947 // video codec without any browser seek. | |
1948 StartConfigChange(false, true, 1, false); | |
1949 | |
1950 // New video codec should have been created and configured, without any | |
1951 // browser seek. | |
1952 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1953 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1954 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
1955 WaitForVideoDecodeDone(); | |
1956 } | |
1957 | |
1958 TEST_F(MediaSourcePlayerTest, VideoDemuxerConfigChangeWithAdaptivePlayback) { | |
1959 // crbug.com/604602 and crbug.com/597836 | |
1960 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
1961 | |
1962 // Test that if codec supports adaptive playback, no new codec should be | |
1963 // created beyond the one used to decode the prefetch media data prior to | |
1964 // the kConfigChanged. | |
1965 StartConfigChange(false, true, 1, true); | |
1966 | |
1967 // No browser seek should be needed. | |
1968 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
1969 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
1970 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
1971 WaitForVideoDecodeDone(); | |
1972 } | |
1973 | |
1974 TEST_F(MediaSourcePlayerTest, DecoderDrainInterruptedBySeek) { | |
1975 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1976 | |
1977 // Test if a decoder is being drained while receiving a seek request, draining | |
1978 // is canceled. | |
1979 SendConfigChangeToDecoder(true, false, 0, false); | |
1980 EXPECT_TRUE(IsDrainingDecoder(true)); | |
1981 | |
1982 player_.SeekTo(base::TimeDelta::FromMilliseconds(100)); | |
1983 WaitForAudioDecodeDone(); | |
1984 EXPECT_FALSE(IsDrainingDecoder(true)); | |
1985 player_.OnDemuxerSeekDone(kNoTimestamp); | |
1986 | |
1987 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
1988 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
1989 } | |
1990 | |
1991 TEST_F(MediaSourcePlayerTest, DecoderDrainInterruptedByRelease) { | |
1992 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
1993 | |
1994 // Test if a decoder is being drained while receiving a release request, | |
1995 // draining is canceled. | |
1996 SendConfigChangeToDecoder(true, false, 0, false); | |
1997 EXPECT_TRUE(IsDrainingDecoder(true)); | |
1998 | |
1999 ReleasePlayer(); | |
2000 WaitForAudioDecodeDone(); | |
2001 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2002 EXPECT_FALSE(IsDrainingDecoder(true)); | |
2003 | |
2004 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
2005 EXPECT_FALSE(player_.IsPlaying()); | |
2006 | |
2007 player_.Start(); | |
2008 EXPECT_TRUE(player_.IsPlaying()); | |
2009 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2010 } | |
2011 | |
2012 TEST_F(MediaSourcePlayerTest, DecoderDrainInterruptedBySurfaceChange) { | |
2013 // crbug.com/604602 and crbug.com/597836 | |
2014 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
2015 | |
2016 // Test if a video decoder is being drained while surface changes, draining | |
2017 // is canceled. | |
2018 SendConfigChangeToDecoder(false, false, 0, false); | |
2019 EXPECT_TRUE(IsDrainingDecoder(false)); | |
2020 | |
2021 CreateNextTextureAndSetVideoSurface(); | |
2022 WaitForVideoDecodeDone(); | |
2023 | |
2024 EXPECT_FALSE(IsDrainingDecoder(false)); | |
2025 EXPECT_TRUE(player_.IsPlaying()); | |
2026 | |
2027 // The frame after the config change should always be an iframe, so no browser | |
2028 // seek is needed when recreating the video decoder due to surface change. | |
2029 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
2030 EXPECT_EQ(4, demuxer_->num_data_requests()); | |
2031 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
2032 } | |
2033 | |
2034 TEST_F(MediaSourcePlayerTest, | |
2035 BrowserSeek_DecoderStarvationWhilePendingSurfaceChange) { | |
2036 // crbug.com/604602 and crbug.com/597836 | |
2037 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
2038 | |
2039 // Test video decoder starvation while handling a pending surface change | |
2040 // should not cause any crashes. | |
2041 CreateNextTextureAndSetVideoSurface(); | |
2042 StartVideoDecoderJob(); | |
2043 DemuxerData data = CreateReadFromDemuxerAckForVideo(false); | |
2044 player_.OnDemuxerDataAvailable(data); | |
2045 | |
2046 // Trigger a surface change and decoder starvation. | |
2047 CreateNextTextureAndSetVideoSurface(); | |
2048 TriggerPlayerStarvation(); | |
2049 WaitForVideoDecodeDone(); | |
2050 EXPECT_EQ(0, demuxer_->num_browser_seek_requests()); | |
2051 | |
2052 // Surface change should trigger a seek. | |
2053 player_.OnDemuxerDataAvailable(data); | |
2054 EXPECT_EQ(1, demuxer_->num_browser_seek_requests()); | |
2055 player_.OnDemuxerSeekDone(base::TimeDelta()); | |
2056 // After seek is done, prefetch is handled first. MediaCodecBridge is not | |
2057 // created at this moment. | |
2058 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
2059 | |
2060 // A new data request should be sent. | |
2061 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2062 } | |
2063 | |
2064 TEST_F(MediaSourcePlayerTest, ReleaseWithOnPrefetchDoneAlreadyPosted) { | |
2065 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2066 | |
2067 // Test if OnPrefetchDone() had already been posted before and is executed | |
2068 // after Release(), then player does not DCHECK. This test is fragile to | |
2069 // change to MediaDecoderJob::Prefetch() implementation; it assumes task | |
2070 // is posted to run |prefetch_cb| if the job already HasData(). | |
2071 // TODO(wolenetz): Remove MSP::set_decode_callback_for_testing() if this test | |
2072 // becomes obsolete. See http://crbug.com/304234. | |
2073 StartAudioDecoderJob(); | |
2074 | |
2075 // Escape the original prefetch by decoding a single access unit. | |
2076 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(0)); | |
2077 WaitForAudioDecodeDone(); | |
2078 | |
2079 // Prime the job with a few more access units, so that a later prefetch, | |
2080 // triggered by starvation to simulate decoder underrun, can trivially | |
2081 // post task to run OnPrefetchDone(). | |
2082 player_.OnDemuxerDataAvailable( | |
2083 CreateReadFromDemuxerAckWithConfigChanged( | |
2084 true, 4, CreateAudioDemuxerConfigs(kCodecVorbis, false))); | |
2085 EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding()); | |
2086 | |
2087 // Simulate decoder underrun, so trivial prefetch starts while still decoding. | |
2088 // The prefetch and posting of OnPrefetchDone() will not occur until next | |
2089 // MediaDecoderCallBack() occurs. | |
2090 TriggerPlayerStarvation(); | |
2091 | |
2092 // Upon the next successful decode callback, post a task to call Release() on | |
2093 // the |player_|, such that the trivial OnPrefetchDone() task posting also | |
2094 // occurs and should execute after the Release(). | |
2095 OnNextTestDecodeCallbackPostTaskToReleasePlayer(); | |
2096 | |
2097 WaitForAudioDecodeDone(); | |
2098 EXPECT_TRUE(decoder_callback_hook_executed_); | |
2099 | |
2100 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2101 | |
2102 // Player should not request any new data since the access units haven't | |
2103 // been fully decoded yet. | |
2104 Resume(false, false); | |
2105 } | |
2106 | |
2107 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekAndDone) { | |
2108 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2109 | |
2110 // Test if Release() occurs after SeekTo(), but the DemuxerSeek IPC request | |
2111 // has not yet been sent, then the seek request is sent after Release(). Also, | |
2112 // test if OnDemuxerSeekDone() occurs prior to next Start(), then the player | |
2113 // will resume correct post-seek preroll upon Start(). | |
2114 StartAudioDecoderJobAndSeekToWhileDecoding( | |
2115 base::TimeDelta::FromMilliseconds(100)); | |
2116 ReleasePlayer(); | |
2117 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
2118 WaitForAudioDecodeDone(); | |
2119 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2120 | |
2121 player_.OnDemuxerSeekDone(kNoTimestamp); | |
2122 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2123 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
2124 EXPECT_FALSE(player_.IsPlaying()); | |
2125 | |
2126 // Player should begin prefetch and resume preroll upon Start(). | |
2127 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2128 Resume(true, false); | |
2129 EXPECT_TRUE(IsPrerolling(true)); | |
2130 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2131 | |
2132 // No further seek should have been requested since Release(), above. | |
2133 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2134 } | |
2135 | |
2136 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenDemuxerSeekThenStart) { | |
2137 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2138 | |
2139 // Test if Release() occurs after SeekTo(), but the DemuxerSeek IPC request | |
2140 // has not yet been sent, then the seek request is sent after Release(). Also, | |
2141 // test if OnDemuxerSeekDone() does not occur until after the next Start(), | |
2142 // then the player remains pending seek done until (and resumes correct | |
2143 // post-seek preroll after) OnDemuxerSeekDone(). | |
2144 StartAudioDecoderJobAndSeekToWhileDecoding( | |
2145 base::TimeDelta::FromMilliseconds(100)); | |
2146 ReleasePlayer(); | |
2147 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
2148 | |
2149 // Player should not prefetch upon Start() nor create the media codec bridge, | |
2150 // due to awaiting DemuxerSeekDone. | |
2151 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2152 Resume(false, false); | |
2153 | |
2154 WaitForAudioDecodeDone(); | |
2155 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2156 player_.OnDemuxerSeekDone(kNoTimestamp); | |
2157 EXPECT_TRUE(GetMediaDecoderJob(true)); | |
2158 EXPECT_TRUE(IsPrerolling(true)); | |
2159 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2160 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2161 | |
2162 // No further seek should have been requested since Release(), above. | |
2163 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2164 } | |
2165 | |
2166 TEST_F(MediaSourcePlayerTest, SeekToThenDemuxerSeekThenReleaseThenSeekDone) { | |
2167 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2168 | |
2169 // Test if Release() occurs after a SeekTo()'s subsequent DemuxerSeek IPC | |
2170 // request and OnDemuxerSeekDone() arrives prior to the next Start(), then the | |
2171 // player will resume correct post-seek preroll upon Start(). | |
2172 StartAudioDecoderJobAndSeekToWhileDecoding( | |
2173 base::TimeDelta::FromMilliseconds(100)); | |
2174 WaitForAudioDecodeDone(); | |
2175 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2176 | |
2177 ReleasePlayer(); | |
2178 player_.OnDemuxerSeekDone(kNoTimestamp); | |
2179 EXPECT_FALSE(player_.IsPlaying()); | |
2180 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
2181 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2182 | |
2183 // Player should begin prefetch and resume preroll upon Start(). | |
2184 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2185 Resume(true, false); | |
2186 EXPECT_TRUE(IsPrerolling(true)); | |
2187 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2188 | |
2189 // No further seek should have been requested since before Release(), above. | |
2190 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2191 } | |
2192 | |
2193 TEST_F(MediaSourcePlayerTest, SeekToThenReleaseThenStart) { | |
2194 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2195 | |
2196 // Test if Release() occurs after a SeekTo()'s subsequent DemuxerSeeK IPC | |
2197 // request and OnDemuxerSeekDone() does not occur until after the next | |
2198 // Start(), then the player remains pending seek done until (and resumes | |
2199 // correct post-seek preroll after) OnDemuxerSeekDone(). | |
2200 StartAudioDecoderJobAndSeekToWhileDecoding( | |
2201 base::TimeDelta::FromMilliseconds(100)); | |
2202 WaitForAudioDecodeDone(); | |
2203 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2204 | |
2205 ReleasePlayer(); | |
2206 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2207 Resume(false, false); | |
2208 | |
2209 player_.OnDemuxerSeekDone(kNoTimestamp); | |
2210 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
2211 EXPECT_TRUE(IsPrerolling(true)); | |
2212 EXPECT_EQ(100.0, GetPrerollTimestamp().InMillisecondsF()); | |
2213 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2214 | |
2215 // No further seek should have been requested since before Release(), above. | |
2216 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2217 } | |
2218 | |
2219 TEST_F(MediaSourcePlayerTest, ConfigChangedThenReleaseThenStart) { | |
2220 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2221 | |
2222 // Test if Release() occurs after |kConfigChanged| is processed, new data | |
2223 // requested of demuxer, and the requested data arrive before the next | |
2224 // Start(), then the player starts to decode the new data without any seek. | |
2225 StartConfigChange(true, true, 0, false); | |
2226 ReleasePlayer(); | |
2227 | |
2228 EXPECT_TRUE(GetMediaCodecBridge(true)); | |
2229 EXPECT_FALSE(player_.IsPlaying()); | |
2230 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2231 player_.OnDemuxerDataAvailable( | |
2232 CreateReadFromDemuxerAckWithConfigChanged( | |
2233 true, 4, CreateAudioDemuxerConfigs(kCodecVorbis, false))); | |
2234 WaitForAudioDecodeDone(); | |
2235 EXPECT_FALSE(GetMediaCodecBridge(true)); | |
2236 | |
2237 // Player should resume upon Start(), even without further configs supplied. | |
2238 player_.Start(); | |
2239 EXPECT_TRUE(player_.IsPlaying()); | |
2240 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2241 EXPECT_EQ(0, demuxer_->num_seek_requests()); | |
2242 WaitForAudioDecodeDone(); | |
2243 } | |
2244 | |
2245 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenDemuxerSeekDone) { | |
2246 // crbug.com/604602 and crbug.com/597836 | |
2247 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
2248 | |
2249 // Test that Release() after a browser seek's DemuxerSeek IPC request has been | |
2250 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() occurs | |
2251 // before the next Start()+SetVideoSurface(), then the player will resume | |
2252 // correct post-seek preroll upon Start()+SetVideoSurface(). | |
2253 BrowserSeekPlayer(false); | |
2254 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
2255 ReleasePlayer(); | |
2256 | |
2257 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
2258 EXPECT_FALSE(player_.IsPlaying()); | |
2259 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
2260 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
2261 | |
2262 // Player should begin prefetch and resume preroll upon Start(). | |
2263 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2264 CreateNextTextureAndSetVideoSurface(); | |
2265 Resume(false, true); | |
2266 EXPECT_TRUE(IsPrerolling(false)); | |
2267 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
2268 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
2269 | |
2270 // No further seek should have been requested since BrowserSeekPlayer(). | |
2271 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2272 } | |
2273 | |
2274 TEST_F(MediaSourcePlayerTest, BrowserSeek_ThenReleaseThenStart) { | |
2275 // crbug.com/604602 and crbug.com/597836 | |
2276 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
2277 | |
2278 // Test that Release() after a browser seek's DemuxerSeek IPC request has been | |
2279 // sent behaves similar to a regular seek: if OnDemuxerSeekDone() does not | |
2280 // occur until after the next Start()+SetVideoSurface(), then the player | |
2281 // remains pending seek done until (and resumes correct post-seek preroll | |
2282 // after) OnDemuxerSeekDone(). | |
2283 BrowserSeekPlayer(false); | |
2284 base::TimeDelta expected_preroll_timestamp = player_.GetCurrentTime(); | |
2285 ReleasePlayer(); | |
2286 | |
2287 EXPECT_EQ(2, demuxer_->num_data_requests()); | |
2288 CreateNextTextureAndSetVideoSurface(); | |
2289 Resume(false, false); | |
2290 | |
2291 player_.OnDemuxerSeekDone(expected_preroll_timestamp); | |
2292 // Prefetch takes place first, and the decoder is not created yet. | |
2293 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
2294 EXPECT_TRUE(IsPrerolling(false)); | |
2295 EXPECT_EQ(expected_preroll_timestamp, GetPrerollTimestamp()); | |
2296 EXPECT_EQ(expected_preroll_timestamp, player_.GetCurrentTime()); | |
2297 EXPECT_EQ(3, demuxer_->num_data_requests()); | |
2298 | |
2299 // No further seek should have been requested since BrowserSeekPlayer(). | |
2300 EXPECT_EQ(1, demuxer_->num_seek_requests()); | |
2301 | |
2302 // Decoder will be created once data is received. | |
2303 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForVideo(false)); | |
2304 EXPECT_TRUE(GetMediaCodecBridge(false)); | |
2305 WaitForVideoDecodeDone(); | |
2306 } | |
2307 | |
2308 // TODO(xhwang): Once we add tests to cover DrmBridge, update this test to | |
2309 // also verify that the job is successfully created if SetDrmBridge(), Start() | |
2310 // and eventually OnMediaCrypto() occur. This would increase test coverage of | |
2311 // http://crbug.com/313470 and allow us to remove inspection of internal player | |
2312 // pending event state. See http://crbug.com/313860. | |
2313 TEST_F(MediaSourcePlayerTest, SurfaceChangeClearedEvenIfMediaCryptoAbsent) { | |
2314 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2315 | |
2316 // Test that |SURFACE_CHANGE_EVENT_PENDING| is not pending after | |
2317 // SetVideoSurface() for a player configured for encrypted video, when the | |
2318 // player has not yet received media crypto. | |
2319 DemuxerConfigs configs = CreateVideoDemuxerConfigs(false); | |
2320 configs.is_video_encrypted = true; | |
2321 | |
2322 player_.OnDemuxerConfigsAvailable(configs); | |
2323 CreateNextTextureAndSetVideoSurface(); | |
2324 EXPECT_FALSE(GetMediaCodecBridge(false)); | |
2325 } | |
2326 | |
2327 TEST_F(MediaSourcePlayerTest, CurrentTimeUpdatedWhileDecoderStarved) { | |
2328 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2329 | |
2330 // Test that current time is updated while decoder is starved. | |
2331 StartAudioDecoderJob(); | |
2332 DecodeAudioDataUntilOutputBecomesAvailable(); | |
2333 | |
2334 // Trigger starvation while the decoder is decoding. | |
2335 player_.OnDemuxerDataAvailable(CreateReadFromDemuxerAckForAudio(3)); | |
2336 manager_.ResetTimestampUpdated(); | |
2337 TriggerPlayerStarvation(); | |
2338 WaitForAudioDecodeDone(); | |
2339 | |
2340 // Current time should be updated. | |
2341 EXPECT_TRUE(manager_.timestamp_updated()); | |
2342 } | |
2343 | |
2344 TEST_F(MediaSourcePlayerTest, CurrentTimeKeepsIncreasingAfterConfigChange) { | |
2345 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2346 | |
2347 // Test current time keep on increasing after audio config change. | |
2348 // Test that current time is updated while decoder is starved. | |
2349 StartAudioDecoderJob(); | |
2350 | |
2351 DecodeAudioDataUntilOutputBecomesAvailable(); | |
2352 | |
2353 DemuxerConfigs configs = CreateAudioDemuxerConfigs(kCodecVorbis, true); | |
2354 DemuxerData data = CreateReadFromDemuxerAckWithConfigChanged( | |
2355 true, 0, configs); | |
2356 player_.OnDemuxerDataAvailable(data); | |
2357 WaitForAudioDecodeDone(); | |
2358 DecodeAudioDataUntilOutputBecomesAvailable(); | |
2359 } | |
2360 | |
2361 TEST_F(MediaSourcePlayerTest, VideoMetadataChangeAfterConfigChange) { | |
2362 // crbug.com/604602 and crbug.com/597836 | |
2363 SKIP_TEST_IF_VP8_DECODER_IS_NOT_SUPPORTED(); | |
2364 | |
2365 // Test that after a config change, metadata change will be happen | |
2366 // after decoder is drained. | |
2367 StartConfigChange(false, true, 2, false); | |
2368 EXPECT_EQ(1, manager_.num_metadata_changes()); | |
2369 EXPECT_FALSE(IsDrainingDecoder(false)); | |
2370 | |
2371 // Create video data with new resolutions. | |
2372 DemuxerData data = CreateReadFromDemuxerAckForVideo(true); | |
2373 | |
2374 // Wait for the metadata change. | |
2375 while(manager_.num_metadata_changes() == 1) { | |
2376 player_.OnDemuxerDataAvailable(data); | |
2377 WaitForVideoDecodeDone(); | |
2378 } | |
2379 EXPECT_EQ(2, manager_.num_metadata_changes()); | |
2380 WaitForVideoDecodeDone(); | |
2381 } | |
2382 | |
2383 TEST_F(MediaSourcePlayerTest, RequestPlayDeniedDontPlay_Audio) { | |
2384 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2385 | |
2386 EXPECT_EQ(demuxer_->num_data_requests(), 0); | |
2387 player_.OnDemuxerConfigsAvailable(CreateDemuxerConfigs(true, false)); | |
2388 | |
2389 manager_.set_allow_play(false); | |
2390 player_.Start(); | |
2391 EXPECT_FALSE(player_.IsPlaying()); | |
2392 } | |
2393 | |
2394 TEST_F(MediaSourcePlayerTest, RequestPlayDeniedDontPlay_Video) { | |
2395 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2396 | |
2397 EXPECT_EQ(demuxer_->num_data_requests(), 0); | |
2398 player_.OnDemuxerConfigsAvailable(CreateDemuxerConfigs(false, true)); | |
2399 | |
2400 manager_.set_allow_play(false); | |
2401 player_.Start(); | |
2402 EXPECT_FALSE(player_.IsPlaying()); | |
2403 } | |
2404 | |
2405 TEST_F(MediaSourcePlayerTest, RequestPlayDeniedDontPlay_AV) { | |
2406 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2407 | |
2408 EXPECT_EQ(demuxer_->num_data_requests(), 0); | |
2409 player_.OnDemuxerConfigsAvailable(CreateDemuxerConfigs(true, true)); | |
2410 | |
2411 manager_.set_allow_play(false); | |
2412 player_.Start(); | |
2413 EXPECT_FALSE(player_.IsPlaying()); | |
2414 } | |
2415 | |
2416 TEST_F(MediaSourcePlayerTest, RequestPlayGrantedPlays) { | |
2417 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
2418 | |
2419 EXPECT_EQ(demuxer_->num_data_requests(), 0); | |
2420 player_.OnDemuxerConfigsAvailable(CreateDemuxerConfigs(true, true)); | |
2421 | |
2422 manager_.set_allow_play(true); | |
2423 player_.Start(); | |
2424 EXPECT_TRUE(player_.IsPlaying()); | |
2425 } | |
2426 | |
2427 } // namespace media | |
OLD | NEW |