OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 ACTION_P(RunClosure, closure) { | 45 ACTION_P(RunClosure, closure) { |
46 closure.Run(); | 46 closure.Run(); |
47 } | 47 } |
48 | 48 |
49 MATCHER_P(HasTimestamp, ms, "") { | 49 MATCHER_P(HasTimestamp, ms, "") { |
50 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); | 50 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); |
51 return arg->timestamp().InMilliseconds() == ms; | 51 return arg->timestamp().InMilliseconds() == ms; |
52 } | 52 } |
53 | 53 |
54 class VideoRendererImplTest | 54 class VideoRendererImplTest : public testing::Test { |
55 : public testing::Test { | |
56 public: | 55 public: |
57 VideoRendererImplTest() | 56 VideoRendererImplTest() |
58 : tick_clock_(new base::SimpleTestTickClock()), | 57 : tick_clock_(new base::SimpleTestTickClock()), |
59 decoder_(new NiceMock<MockVideoDecoder>()), | 58 decoder_(new NiceMock<MockVideoDecoder>()), |
60 demuxer_stream_(DemuxerStream::VIDEO) { | 59 demuxer_stream_(DemuxerStream::VIDEO) { |
61 ScopedVector<VideoDecoder> decoders; | 60 ScopedVector<VideoDecoder> decoders; |
62 decoders.push_back(decoder_); | 61 decoders.push_back(decoder_); |
63 | 62 |
64 null_video_sink_.reset(new NullVideoSink( | 63 null_video_sink_.reset(new NullVideoSink( |
65 false, base::TimeDelta::FromSecondsD(1.0 / 60), | 64 false, base::TimeDelta::FromSecondsD(1.0 / 60), |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 } | 112 } |
114 | 113 |
115 void CallInitialize(const PipelineStatusCB& status_cb, | 114 void CallInitialize(const PipelineStatusCB& status_cb, |
116 bool low_delay, | 115 bool low_delay, |
117 bool expect_success) { | 116 bool expect_success) { |
118 if (low_delay) | 117 if (low_delay) |
119 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE); | 118 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE); |
120 EXPECT_CALL(*decoder_, Initialize(_, _, _, _, _)) | 119 EXPECT_CALL(*decoder_, Initialize(_, _, _, _, _)) |
121 .WillOnce( | 120 .WillOnce( |
122 DoAll(SaveArg<4>(&output_cb_), RunCallback<3>(expect_success))); | 121 DoAll(SaveArg<4>(&output_cb_), RunCallback<3>(expect_success))); |
123 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | 122 EXPECT_CALL(mock_cb_, OnWaitingForDecryptionKey()).Times(0); |
124 renderer_->Initialize( | 123 renderer_->Initialize(&demuxer_stream_, nullptr, &mock_cb_, |
125 &demuxer_stream_, status_cb, nullptr, | 124 base::Bind(&WallClockTimeSource::GetWallClockTimes, |
126 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate, | 125 base::Unretained(&time_source_)), |
127 base::Unretained(this)), | 126 status_cb); |
128 base::Bind(&StrictMock<MockCB>::BufferingStateChange, | |
129 base::Unretained(&mock_cb_)), | |
130 ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(), | |
131 base::Bind(&WallClockTimeSource::GetWallClockTimes, | |
132 base::Unretained(&time_source_)), | |
133 base::Bind(&VideoRendererImplTest::OnWaitingForDecryptionKey, | |
134 base::Unretained(this))); | |
135 } | 127 } |
136 | 128 |
137 void StartPlayingFrom(int milliseconds) { | 129 void StartPlayingFrom(int milliseconds) { |
138 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds)); | 130 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds)); |
139 const base::TimeDelta media_time = | 131 const base::TimeDelta media_time = |
140 base::TimeDelta::FromMilliseconds(milliseconds); | 132 base::TimeDelta::FromMilliseconds(milliseconds); |
141 time_source_.SetMediaTime(media_time); | 133 time_source_.SetMediaTime(media_time); |
142 renderer_->StartPlayingFrom(media_time); | 134 renderer_->StartPlayingFrom(media_time); |
143 message_loop_.RunUntilIdle(); | 135 message_loop_.RunUntilIdle(); |
144 } | 136 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 CHECK(false) << "Unrecognized decoder buffer token: " << token; | 190 CHECK(false) << "Unrecognized decoder buffer token: " << token; |
199 } | 191 } |
200 } | 192 } |
201 | 193 |
202 bool IsReadPending() { | 194 bool IsReadPending() { |
203 return !decode_cb_.is_null(); | 195 return !decode_cb_.is_null(); |
204 } | 196 } |
205 | 197 |
206 void WaitForError(PipelineStatus expected) { | 198 void WaitForError(PipelineStatus expected) { |
207 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); | 199 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); |
208 error_event_.RunAndWaitForStatus(expected); | 200 |
| 201 WaitableMessageLoopEvent event; |
| 202 PipelineStatusCB error_cb = event.GetPipelineStatusCB(); |
| 203 EXPECT_CALL(mock_cb_, OnError(_)) |
| 204 .WillOnce(Invoke(&error_cb, &PipelineStatusCB::Run)); |
| 205 event.RunAndWaitForStatus(expected); |
209 } | 206 } |
210 | 207 |
211 void WaitForEnded() { | 208 void WaitForEnded() { |
212 SCOPED_TRACE("WaitForEnded()"); | 209 SCOPED_TRACE("WaitForEnded()"); |
213 ended_event_.RunAndWait(); | 210 |
| 211 WaitableMessageLoopEvent event; |
| 212 EXPECT_CALL(mock_cb_, OnEnded()).WillOnce(RunClosure(event.GetClosure())); |
| 213 event.RunAndWait(); |
214 } | 214 } |
215 | 215 |
216 void WaitForPendingRead() { | 216 void WaitForPendingRead() { |
217 SCOPED_TRACE("WaitForPendingRead()"); | 217 SCOPED_TRACE("WaitForPendingRead()"); |
218 if (!decode_cb_.is_null()) | 218 if (!decode_cb_.is_null()) |
219 return; | 219 return; |
220 | 220 |
221 DCHECK(wait_for_pending_decode_cb_.is_null()); | 221 DCHECK(wait_for_pending_decode_cb_.is_null()); |
222 | 222 |
223 WaitableMessageLoopEvent event; | 223 WaitableMessageLoopEvent event; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 270 |
271 void AdvanceTimeInMs(int time_ms) { | 271 void AdvanceTimeInMs(int time_ms) { |
272 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 272 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
273 base::AutoLock l(lock_); | 273 base::AutoLock l(lock_); |
274 time_ += base::TimeDelta::FromMilliseconds(time_ms); | 274 time_ += base::TimeDelta::FromMilliseconds(time_ms); |
275 time_source_.StopTicking(); | 275 time_source_.StopTicking(); |
276 time_source_.SetMediaTime(time_); | 276 time_source_.SetMediaTime(time_); |
277 time_source_.StartTicking(); | 277 time_source_.StartTicking(); |
278 } | 278 } |
279 | 279 |
280 bool has_ended() const { | |
281 return ended_event_.is_signaled(); | |
282 } | |
283 | |
284 enum class UnderflowTestType { | 280 enum class UnderflowTestType { |
285 NORMAL, | 281 NORMAL, |
286 LOW_DELAY, | 282 LOW_DELAY, |
287 CANT_READ_WITHOUT_STALLING | 283 CANT_READ_WITHOUT_STALLING |
288 }; | 284 }; |
289 void BasicUnderflowTest(UnderflowTestType type) { | 285 void BasicUnderflowTest(UnderflowTestType type) { |
290 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); | 286 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
291 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) | 287 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
292 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 288 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
293 | 289 |
294 QueueFrames("0 30 60 90"); | 290 QueueFrames("0 30 60 90"); |
295 | 291 |
296 { | 292 { |
297 WaitableMessageLoopEvent event; | 293 WaitableMessageLoopEvent event; |
298 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 294 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
299 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 295 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
300 .WillOnce(RunClosure(event.GetClosure())); | 296 .WillOnce(RunClosure(event.GetClosure())); |
| 297 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
301 StartPlayingFrom(0); | 298 StartPlayingFrom(0); |
302 event.RunAndWait(); | 299 event.RunAndWait(); |
303 Mock::VerifyAndClearExpectations(&mock_cb_); | 300 Mock::VerifyAndClearExpectations(&mock_cb_); |
304 } | 301 } |
305 | 302 |
306 renderer_->OnTimeStateChanged(true); | 303 renderer_->OnTimeStateChanged(true); |
307 | 304 |
308 // Advance time slightly, but enough to exceed the duration of the last | 305 // Advance time slightly, but enough to exceed the duration of the last |
309 // frame. | 306 // frame. |
310 // Frames should be dropped and we should NOT signal having nothing. | 307 // Frames should be dropped and we should NOT signal having nothing. |
311 { | 308 { |
312 SCOPED_TRACE("Waiting for frame drops"); | 309 SCOPED_TRACE("Waiting for frame drops"); |
313 WaitableMessageLoopEvent event; | 310 WaitableMessageLoopEvent event; |
314 | 311 |
315 // Note: Starting the TimeSource will cause the old VideoRendererImpl to | 312 // Note: Starting the TimeSource will cause the old VideoRendererImpl to |
316 // start rendering frames on its own thread, so the first frame may be | 313 // start rendering frames on its own thread, so the first frame may be |
317 // received. | 314 // received. |
318 time_source_.StartTicking(); | 315 time_source_.StartTicking(); |
319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); | 316 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); |
320 | 317 |
321 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); | 318 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); |
322 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) | 319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) |
323 .WillOnce(RunClosure(event.GetClosure())); | 320 .WillOnce(RunClosure(event.GetClosure())); |
| 321 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
324 AdvanceTimeInMs(91); | 322 AdvanceTimeInMs(91); |
325 | 323 |
326 event.RunAndWait(); | 324 event.RunAndWait(); |
327 Mock::VerifyAndClearExpectations(&mock_cb_); | 325 Mock::VerifyAndClearExpectations(&mock_cb_); |
328 } | 326 } |
329 | 327 |
330 // Advance time more. Now we should signal having nothing. And put | 328 // Advance time more. Now we should signal having nothing. And put |
331 // the last frame up for display. | 329 // the last frame up for display. |
332 { | 330 { |
333 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | 331 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
334 WaitableMessageLoopEvent event; | 332 WaitableMessageLoopEvent event; |
335 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 333 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
336 .WillOnce(RunClosure(event.GetClosure())); | 334 .WillOnce(RunClosure(event.GetClosure())); |
337 AdvanceTimeInMs(30); | 335 AdvanceTimeInMs(30); |
338 event.RunAndWait(); | 336 event.RunAndWait(); |
339 Mock::VerifyAndClearExpectations(&mock_cb_); | 337 Mock::VerifyAndClearExpectations(&mock_cb_); |
340 } | 338 } |
341 | 339 |
342 // Simulate delayed buffering state callbacks. | 340 // Simulate delayed buffering state callbacks. |
343 renderer_->OnTimeStateChanged(false); | 341 renderer_->OnTimeStateChanged(false); |
344 renderer_->OnTimeStateChanged(true); | 342 renderer_->OnTimeStateChanged(true); |
345 | 343 |
346 // Receiving end of stream should signal having enough. | 344 // Receiving end of stream should signal having enough. |
347 { | 345 { |
348 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 346 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
349 WaitableMessageLoopEvent event; | 347 WaitableMessageLoopEvent event; |
350 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 348 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
351 .WillOnce(RunClosure(event.GetClosure())); | 349 .WillOnce(RunClosure(event.GetClosure())); |
| 350 EXPECT_CALL(mock_cb_, OnEnded()); |
352 SatisfyPendingReadWithEndOfStream(); | 351 SatisfyPendingReadWithEndOfStream(); |
353 event.RunAndWait(); | 352 event.RunAndWait(); |
354 } | 353 } |
355 | 354 |
356 WaitForEnded(); | |
357 Destroy(); | 355 Destroy(); |
358 } | 356 } |
359 | 357 |
360 void UnderflowRecoveryTest(UnderflowTestType type) { | 358 void UnderflowRecoveryTest(UnderflowTestType type) { |
361 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); | 359 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
362 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) | 360 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
363 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 361 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
364 | 362 |
365 QueueFrames("0 20 40 60"); | 363 QueueFrames("0 20 40 60"); |
366 { | 364 { |
367 WaitableMessageLoopEvent event; | 365 WaitableMessageLoopEvent event; |
368 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 366 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
369 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 367 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
370 .WillOnce(RunClosure(event.GetClosure())); | 368 .WillOnce(RunClosure(event.GetClosure())); |
| 369 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
371 StartPlayingFrom(0); | 370 StartPlayingFrom(0); |
372 event.RunAndWait(); | 371 event.RunAndWait(); |
373 Mock::VerifyAndClearExpectations(&mock_cb_); | 372 Mock::VerifyAndClearExpectations(&mock_cb_); |
374 } | 373 } |
375 | 374 |
376 renderer_->OnTimeStateChanged(true); | 375 renderer_->OnTimeStateChanged(true); |
377 time_source_.StartTicking(); | 376 time_source_.StartTicking(); |
378 | 377 |
379 // Advance time, this should cause have nothing to be signaled. | 378 // Advance time, this should cause have nothing to be signaled. |
380 { | 379 { |
381 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | 380 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
382 WaitableMessageLoopEvent event; | 381 WaitableMessageLoopEvent event; |
383 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 382 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
384 .WillOnce(RunClosure(event.GetClosure())); | 383 .WillOnce(RunClosure(event.GetClosure())); |
385 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); | 384 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); |
| 385 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
386 AdvanceTimeInMs(20); | 386 AdvanceTimeInMs(20); |
387 event.RunAndWait(); | 387 event.RunAndWait(); |
388 Mock::VerifyAndClearExpectations(&mock_cb_); | 388 Mock::VerifyAndClearExpectations(&mock_cb_); |
389 } | 389 } |
390 | 390 |
391 AdvanceTimeInMs(59); | 391 AdvanceTimeInMs(59); |
392 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); | 392 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); |
393 time_source_.StopTicking(); | 393 time_source_.StopTicking(); |
394 renderer_->OnTimeStateChanged(false); | 394 renderer_->OnTimeStateChanged(false); |
395 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); | 395 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); |
396 ASSERT_TRUE(IsReadPending()); | 396 ASSERT_TRUE(IsReadPending()); |
397 | 397 |
398 // Queue some frames, satisfy reads, and make sure expired frames are gone | 398 // Queue some frames, satisfy reads, and make sure expired frames are gone |
399 // when the renderer paints the first frame. | 399 // when the renderer paints the first frame. |
400 { | 400 { |
401 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 401 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
402 WaitableMessageLoopEvent event; | 402 WaitableMessageLoopEvent event; |
403 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); | 403 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); |
404 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 404 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
405 .WillOnce(RunClosure(event.GetClosure())); | 405 .WillOnce(RunClosure(event.GetClosure())); |
406 if (type == UnderflowTestType::NORMAL) | 406 if (type == UnderflowTestType::NORMAL) |
407 QueueFrames("80 100 120 140 160"); | 407 QueueFrames("80 100 120 140 160"); |
408 else | 408 else |
409 QueueFrames("40 60 80"); | 409 QueueFrames("40 60 80"); |
410 SatisfyPendingRead(); | 410 SatisfyPendingRead(); |
411 event.RunAndWait(); | 411 event.RunAndWait(); |
412 } | 412 } |
413 | 413 |
414 Destroy(); | 414 Destroy(); |
415 } | 415 } |
416 | 416 |
417 protected: | 417 protected: |
418 // Fixture members. | 418 // Fixture members. |
419 std::unique_ptr<VideoRendererImpl> renderer_; | 419 std::unique_ptr<VideoRendererImpl> renderer_; |
420 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. | 420 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. |
421 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. | 421 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. |
422 NiceMock<MockDemuxerStream> demuxer_stream_; | 422 NiceMock<MockDemuxerStream> demuxer_stream_; |
423 | 423 |
424 // Use StrictMock<T> to catch missing/extra callbacks. | 424 // Use StrictMock<T> to catch missing/extra callbacks. |
425 class MockCB { | 425 class MockCB : public MockRendererClient { |
426 public: | 426 public: |
427 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&)); | 427 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&)); |
428 MOCK_METHOD1(BufferingStateChange, void(BufferingState)); | |
429 }; | 428 }; |
430 StrictMock<MockCB> mock_cb_; | 429 StrictMock<MockCB> mock_cb_; |
431 | 430 |
432 // Must be destroyed before |renderer_| since they share |tick_clock_|. | 431 // Must be destroyed before |renderer_| since they share |tick_clock_|. |
433 std::unique_ptr<NullVideoSink> null_video_sink_; | 432 std::unique_ptr<NullVideoSink> null_video_sink_; |
434 | 433 |
435 PipelineStatistics last_pipeline_statistics_; | |
436 | |
437 WallClockTimeSource time_source_; | 434 WallClockTimeSource time_source_; |
438 | 435 |
439 base::MessageLoop message_loop_; | 436 base::MessageLoop message_loop_; |
440 | 437 |
441 private: | 438 private: |
442 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer, | 439 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer, |
443 const VideoDecoder::DecodeCB& decode_cb) { | 440 const VideoDecoder::DecodeCB& decode_cb) { |
444 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 441 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
445 CHECK(decode_cb_.is_null()); | 442 CHECK(decode_cb_.is_null()); |
446 decode_cb_ = decode_cb; | 443 decode_cb_ = decode_cb; |
(...skipping 12 matching lines...) Expand all Loading... |
459 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 456 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
460 decode_results_.clear(); | 457 decode_results_.clear(); |
461 if (!decode_cb_.is_null()) { | 458 if (!decode_cb_.is_null()) { |
462 QueueFrames("abort"); | 459 QueueFrames("abort"); |
463 SatisfyPendingRead(); | 460 SatisfyPendingRead(); |
464 } | 461 } |
465 | 462 |
466 message_loop_.PostTask(FROM_HERE, callback); | 463 message_loop_.PostTask(FROM_HERE, callback); |
467 } | 464 } |
468 | 465 |
469 void OnStatisticsUpdate(const PipelineStatistics& stats) { | |
470 last_pipeline_statistics_ = stats; | |
471 } | |
472 | |
473 MOCK_METHOD0(OnWaitingForDecryptionKey, void(void)); | |
474 | |
475 // Used to protect |time_|. | 466 // Used to protect |time_|. |
476 base::Lock lock_; | 467 base::Lock lock_; |
477 base::TimeDelta time_; | 468 base::TimeDelta time_; |
478 | 469 |
479 // Used for satisfying reads. | 470 // Used for satisfying reads. |
480 VideoDecoder::OutputCB output_cb_; | 471 VideoDecoder::OutputCB output_cb_; |
481 VideoDecoder::DecodeCB decode_cb_; | 472 VideoDecoder::DecodeCB decode_cb_; |
482 base::TimeDelta next_frame_timestamp_; | 473 base::TimeDelta next_frame_timestamp_; |
483 | 474 |
484 WaitableMessageLoopEvent error_event_; | |
485 WaitableMessageLoopEvent ended_event_; | |
486 | |
487 // Run during DecodeRequested() to unblock WaitForPendingRead(). | 475 // Run during DecodeRequested() to unblock WaitForPendingRead(). |
488 base::Closure wait_for_pending_decode_cb_; | 476 base::Closure wait_for_pending_decode_cb_; |
489 | 477 |
490 std::deque<std::pair<DecodeStatus, scoped_refptr<VideoFrame>>> | 478 std::deque<std::pair<DecodeStatus, scoped_refptr<VideoFrame>>> |
491 decode_results_; | 479 decode_results_; |
492 | 480 |
493 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); | 481 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); |
494 }; | 482 }; |
495 | 483 |
496 TEST_F(VideoRendererImplTest, DoNothing) { | 484 TEST_F(VideoRendererImplTest, DoNothing) { |
497 // Test that creation and deletion doesn't depend on calls to Initialize() | 485 // Test that creation and deletion doesn't depend on calls to Initialize() |
498 // and/or Destroy(). | 486 // and/or Destroy(). |
499 } | 487 } |
500 | 488 |
501 TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) { | 489 TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) { |
502 Destroy(); | 490 Destroy(); |
503 } | 491 } |
504 | 492 |
505 TEST_F(VideoRendererImplTest, Initialize) { | 493 TEST_F(VideoRendererImplTest, Initialize) { |
506 Initialize(); | 494 Initialize(); |
507 Destroy(); | 495 Destroy(); |
508 } | 496 } |
509 | 497 |
510 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) { | 498 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) { |
511 Initialize(); | 499 Initialize(); |
512 QueueFrames("0 10 20 30"); | 500 QueueFrames("0 10 20 30"); |
513 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 501 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
514 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 502 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 503 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
515 StartPlayingFrom(0); | 504 StartPlayingFrom(0); |
516 Destroy(); | 505 Destroy(); |
517 } | 506 } |
518 | 507 |
519 TEST_F(VideoRendererImplTest, InitializeAndEndOfStream) { | 508 TEST_F(VideoRendererImplTest, InitializeAndEndOfStream) { |
520 Initialize(); | 509 Initialize(); |
521 StartPlayingFrom(0); | 510 StartPlayingFrom(0); |
522 WaitForPendingRead(); | 511 WaitForPendingRead(); |
523 { | 512 { |
524 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 513 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
525 WaitableMessageLoopEvent event; | 514 WaitableMessageLoopEvent event; |
526 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 515 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
527 .WillOnce(RunClosure(event.GetClosure())); | 516 .WillOnce(RunClosure(event.GetClosure())); |
| 517 EXPECT_CALL(mock_cb_, OnEnded()); |
528 SatisfyPendingReadWithEndOfStream(); | 518 SatisfyPendingReadWithEndOfStream(); |
529 event.RunAndWait(); | 519 event.RunAndWait(); |
530 } | 520 } |
531 // Firing a time state changed to true should be ignored... | 521 // Firing a time state changed to true should be ignored... |
532 renderer_->OnTimeStateChanged(true); | 522 renderer_->OnTimeStateChanged(true); |
533 EXPECT_FALSE(null_video_sink_->is_started()); | 523 EXPECT_FALSE(null_video_sink_->is_started()); |
534 Destroy(); | 524 Destroy(); |
535 } | 525 } |
536 | 526 |
537 TEST_F(VideoRendererImplTest, DestroyWhileInitializing) { | 527 TEST_F(VideoRendererImplTest, DestroyWhileInitializing) { |
538 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK); | 528 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK); |
539 Destroy(); | 529 Destroy(); |
540 } | 530 } |
541 | 531 |
542 TEST_F(VideoRendererImplTest, DestroyWhileFlushing) { | 532 TEST_F(VideoRendererImplTest, DestroyWhileFlushing) { |
543 Initialize(); | 533 Initialize(); |
544 QueueFrames("0 10 20 30"); | 534 QueueFrames("0 10 20 30"); |
545 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 535 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
546 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 536 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 537 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
547 StartPlayingFrom(0); | 538 StartPlayingFrom(0); |
548 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)); | |
549 renderer_->Flush(NewExpectedClosure()); | 539 renderer_->Flush(NewExpectedClosure()); |
550 Destroy(); | 540 Destroy(); |
551 } | 541 } |
552 | 542 |
553 TEST_F(VideoRendererImplTest, Play) { | 543 TEST_F(VideoRendererImplTest, Play) { |
554 Initialize(); | 544 Initialize(); |
555 QueueFrames("0 10 20 30"); | 545 QueueFrames("0 10 20 30"); |
556 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 546 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
557 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 547 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 548 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
558 StartPlayingFrom(0); | 549 StartPlayingFrom(0); |
559 Destroy(); | 550 Destroy(); |
560 } | 551 } |
561 | 552 |
562 TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) { | 553 TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) { |
563 Initialize(); | 554 Initialize(); |
564 StartPlayingFrom(0); | 555 StartPlayingFrom(0); |
565 | 556 |
566 // We shouldn't expect a buffering state change since we never reached | 557 // We shouldn't expect a buffering state change since we never reached |
567 // BUFFERING_HAVE_ENOUGH. | 558 // BUFFERING_HAVE_ENOUGH. |
568 Flush(); | 559 Flush(); |
569 Destroy(); | 560 Destroy(); |
570 } | 561 } |
571 | 562 |
572 TEST_F(VideoRendererImplTest, DecodeError_Playing) { | 563 TEST_F(VideoRendererImplTest, DecodeError_Playing) { |
573 Initialize(); | 564 Initialize(); |
574 QueueFrames("0 10 20 30"); | 565 QueueFrames("0 10 20 30"); |
575 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1)); | 566 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1)); |
576 | 567 |
577 // Consider the case that rendering is faster than we setup the test event. | 568 // Consider the case that rendering is faster than we setup the test event. |
578 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will | 569 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will |
579 // be called. | 570 // be called. |
580 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 571 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
581 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 572 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
582 .Times(testing::AtMost(1)); | 573 .Times(testing::AtMost(1)); |
| 574 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
583 | 575 |
584 StartPlayingFrom(0); | 576 StartPlayingFrom(0); |
585 renderer_->OnTimeStateChanged(true); | 577 renderer_->OnTimeStateChanged(true); |
586 time_source_.StartTicking(); | 578 time_source_.StartTicking(); |
587 AdvanceTimeInMs(10); | 579 AdvanceTimeInMs(10); |
588 | 580 |
589 QueueFrames("error"); | 581 QueueFrames("error"); |
590 SatisfyPendingRead(); | 582 SatisfyPendingRead(); |
591 WaitForError(PIPELINE_ERROR_DECODE); | 583 WaitForError(PIPELINE_ERROR_DECODE); |
592 Destroy(); | 584 Destroy(); |
593 } | 585 } |
594 | 586 |
595 TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) { | 587 TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) { |
596 Initialize(); | 588 Initialize(); |
597 QueueFrames("error"); | 589 QueueFrames("error"); |
| 590 EXPECT_CALL(mock_cb_, OnError(PIPELINE_ERROR_DECODE)); |
598 StartPlayingFrom(0); | 591 StartPlayingFrom(0); |
599 Destroy(); | 592 Destroy(); |
600 } | 593 } |
601 | 594 |
602 TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) { | 595 TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) { |
603 Initialize(); | 596 Initialize(); |
604 QueueFrames("50 60 70 80 90"); | 597 QueueFrames("50 60 70 80 90"); |
605 | 598 |
606 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); | 599 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); |
607 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 600 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 601 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
608 StartPlayingFrom(60); | 602 StartPlayingFrom(60); |
609 Destroy(); | 603 Destroy(); |
610 } | 604 } |
611 | 605 |
612 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) { | 606 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) { |
613 Initialize(); | 607 Initialize(); |
614 QueueFrames("50 60 70 80 90"); | 608 QueueFrames("50 60 70 80 90"); |
615 | 609 |
616 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50))); | 610 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50))); |
617 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 611 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 612 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
618 StartPlayingFrom(59); | 613 StartPlayingFrom(59); |
619 Destroy(); | 614 Destroy(); |
620 } | 615 } |
621 | 616 |
622 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) { | 617 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) { |
623 Initialize(); | 618 Initialize(); |
624 QueueFrames("50 60 70 80 90"); | 619 QueueFrames("50 60 70 80 90"); |
625 | 620 |
626 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); | 621 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); |
627 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 622 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 623 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
628 StartPlayingFrom(61); | 624 StartPlayingFrom(61); |
629 Destroy(); | 625 Destroy(); |
630 } | 626 } |
631 | 627 |
632 TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) { | 628 TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) { |
633 // In low-delay mode only one frame is required to finish preroll. But frames | 629 // In low-delay mode only one frame is required to finish preroll. But frames |
634 // prior to the start time will not be used. | 630 // prior to the start time will not be used. |
635 InitializeWithLowDelay(true); | 631 InitializeWithLowDelay(true); |
636 QueueFrames("0 10"); | 632 QueueFrames("0 10"); |
637 | 633 |
638 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))); | 634 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))); |
639 // Expect some amount of have enough/nothing due to only requiring one frame. | 635 // Expect some amount of have enough/nothing due to only requiring one frame. |
640 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 636 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
641 .Times(AnyNumber()); | 637 .Times(AnyNumber()); |
642 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 638 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
643 .Times(AnyNumber()); | 639 .Times(AnyNumber()); |
| 640 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
644 StartPlayingFrom(10); | 641 StartPlayingFrom(10); |
645 | 642 |
646 QueueFrames("20"); | 643 QueueFrames("20"); |
647 SatisfyPendingRead(); | 644 SatisfyPendingRead(); |
648 | 645 |
649 renderer_->OnTimeStateChanged(true); | 646 renderer_->OnTimeStateChanged(true); |
650 time_source_.StartTicking(); | 647 time_source_.StartTicking(); |
651 | 648 |
652 WaitableMessageLoopEvent event; | 649 WaitableMessageLoopEvent event; |
653 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))) | 650 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))) |
654 .WillOnce(RunClosure(event.GetClosure())); | 651 .WillOnce(RunClosure(event.GetClosure())); |
655 AdvanceTimeInMs(20); | 652 AdvanceTimeInMs(20); |
656 event.RunAndWait(); | 653 event.RunAndWait(); |
657 | 654 |
658 Destroy(); | 655 Destroy(); |
659 } | 656 } |
660 | 657 |
661 // Verify that a late decoder response doesn't break invariants in the renderer. | 658 // Verify that a late decoder response doesn't break invariants in the renderer. |
662 TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) { | 659 TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) { |
663 Initialize(); | 660 Initialize(); |
664 QueueFrames("0 10 20 30"); | 661 QueueFrames("0 10 20 30"); |
665 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 662 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
666 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 663 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 664 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
667 StartPlayingFrom(0); | 665 StartPlayingFrom(0); |
668 | 666 |
669 // Check that there is an outstanding Read() request. | 667 // Check that there is an outstanding Read() request. |
670 EXPECT_TRUE(IsReadPending()); | 668 EXPECT_TRUE(IsReadPending()); |
671 | 669 |
672 Destroy(); | 670 Destroy(); |
673 } | 671 } |
674 | 672 |
675 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { | 673 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { |
676 InitializeRenderer(false, false); | 674 InitializeRenderer(false, false); |
(...skipping 24 matching lines...) Expand all Loading... |
701 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); | 699 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); |
702 } | 700 } |
703 | 701 |
704 // Verifies that the sink is stopped after rendering the first frame if | 702 // Verifies that the sink is stopped after rendering the first frame if |
705 // playback hasn't started. | 703 // playback hasn't started. |
706 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { | 704 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { |
707 InitializeWithLowDelay(true); | 705 InitializeWithLowDelay(true); |
708 QueueFrames("0"); | 706 QueueFrames("0"); |
709 | 707 |
710 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 708 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
711 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 709 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 710 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 711 EXPECT_CALL(mock_cb_, OnEnded()).Times(0); |
712 | 712 |
713 { | 713 { |
714 SCOPED_TRACE("Waiting for sink to stop."); | 714 SCOPED_TRACE("Waiting for sink to stop."); |
715 WaitableMessageLoopEvent event; | 715 WaitableMessageLoopEvent event; |
716 | 716 |
717 null_video_sink_->set_background_render(true); | 717 null_video_sink_->set_background_render(true); |
718 null_video_sink_->set_stop_cb(event.GetClosure()); | 718 null_video_sink_->set_stop_cb(event.GetClosure()); |
719 StartPlayingFrom(0); | 719 StartPlayingFrom(0); |
720 | 720 |
721 EXPECT_TRUE(IsReadPending()); | 721 EXPECT_TRUE(IsReadPending()); |
722 SatisfyPendingReadWithEndOfStream(); | 722 SatisfyPendingReadWithEndOfStream(); |
723 | 723 |
724 event.RunAndWait(); | 724 event.RunAndWait(); |
725 } | 725 } |
726 | 726 |
727 EXPECT_FALSE(has_ended()); | |
728 Destroy(); | 727 Destroy(); |
729 } | 728 } |
730 | 729 |
731 // Verifies that the sink is stopped after rendering the first frame if | 730 // Verifies that the sink is stopped after rendering the first frame if |
732 // playback ha started. | 731 // playback ha started. |
733 TEST_F(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) { | 732 TEST_F(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) { |
734 InitializeWithLowDelay(true); | 733 InitializeWithLowDelay(true); |
735 QueueFrames("0"); | 734 QueueFrames("0"); |
736 | 735 |
737 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 736 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
738 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 737 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 738 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
739 | 739 |
740 { | 740 { |
741 SCOPED_TRACE("Waiting for sink to stop."); | 741 SCOPED_TRACE("Waiting for sink to stop."); |
742 WaitableMessageLoopEvent event; | 742 WaitableMessageLoopEvent event; |
743 | 743 |
744 null_video_sink_->set_stop_cb(event.GetClosure()); | 744 null_video_sink_->set_stop_cb(event.GetClosure()); |
745 StartPlayingFrom(0); | 745 StartPlayingFrom(0); |
746 renderer_->OnTimeStateChanged(true); | 746 renderer_->OnTimeStateChanged(true); |
747 | 747 |
748 EXPECT_TRUE(IsReadPending()); | 748 EXPECT_TRUE(IsReadPending()); |
749 SatisfyPendingReadWithEndOfStream(); | 749 SatisfyPendingReadWithEndOfStream(); |
750 WaitForEnded(); | 750 WaitForEnded(); |
751 | 751 |
752 renderer_->OnTimeStateChanged(false); | 752 renderer_->OnTimeStateChanged(false); |
753 event.RunAndWait(); | 753 event.RunAndWait(); |
754 } | 754 } |
755 | 755 |
756 Destroy(); | 756 Destroy(); |
757 } | 757 } |
758 | 758 |
759 // Tests the case where the video started and received a single Render() call, | 759 // Tests the case where the video started and received a single Render() call, |
760 // then the video was put into the background. | 760 // then the video was put into the background. |
761 TEST_F(VideoRendererImplTest, RenderingStartedThenStopped) { | 761 TEST_F(VideoRendererImplTest, RenderingStartedThenStopped) { |
762 Initialize(); | 762 Initialize(); |
763 QueueFrames("0 30 60 90"); | 763 QueueFrames("0 30 60 90"); |
764 | 764 |
765 // Start the sink and wait for the first callback. Set statistics to a non | 765 // Start the sink and wait for the first callback. Set statistics to a non |
766 // zero value, once we have some decoded frames they should be overwritten. | 766 // zero value, once we have some decoded frames they should be overwritten. |
767 last_pipeline_statistics_.video_frames_dropped = 1; | 767 PipelineStatistics last_pipeline_statistics; |
| 768 last_pipeline_statistics.video_frames_dropped = 1; |
768 { | 769 { |
769 WaitableMessageLoopEvent event; | 770 WaitableMessageLoopEvent event; |
770 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 771 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
771 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))) | 772 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))) |
772 .WillOnce(RunClosure(event.GetClosure())); | 773 .WillOnce(RunClosure(event.GetClosure())); |
| 774 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)) |
| 775 .WillRepeatedly(SaveArg<0>(&last_pipeline_statistics)); |
773 StartPlayingFrom(0); | 776 StartPlayingFrom(0); |
774 event.RunAndWait(); | 777 event.RunAndWait(); |
775 Mock::VerifyAndClearExpectations(&mock_cb_); | 778 Mock::VerifyAndClearExpectations(&mock_cb_); |
776 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped); | 779 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped); |
777 EXPECT_EQ(460800, last_pipeline_statistics_.video_memory_usage); | 780 EXPECT_EQ(460800, last_pipeline_statistics.video_memory_usage); |
778 } | 781 } |
779 | 782 |
780 // Consider the case that rendering is faster than we setup the test event. | 783 // Consider the case that rendering is faster than we setup the test event. |
781 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will | 784 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will |
782 // be called. And then during SatisfyPendingReadWithEndOfStream, | 785 // be called. And then during SatisfyPendingReadWithEndOfStream, |
783 // BUFFER_HAVE_ENOUGH will be called again. | 786 // BUFFER_HAVE_ENOUGH will be called again. |
784 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 787 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
785 .Times(testing::AtMost(1)); | 788 .Times(testing::AtMost(1)); |
786 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 789 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
787 .Times(testing::AtMost(1)); | 790 .Times(testing::AtMost(1)); |
788 renderer_->OnTimeStateChanged(true); | 791 renderer_->OnTimeStateChanged(true); |
789 time_source_.StartTicking(); | 792 time_source_.StartTicking(); |
790 | 793 |
791 // Suspend all future callbacks and synthetically advance the media time, | 794 // Suspend all future callbacks and synthetically advance the media time, |
792 // because this is a background render, we won't underflow by waiting until | 795 // because this is a background render, we won't underflow by waiting until |
793 // a pending read is ready. | 796 // a pending read is ready. |
794 null_video_sink_->set_background_render(true); | 797 null_video_sink_->set_background_render(true); |
795 AdvanceTimeInMs(91); | 798 AdvanceTimeInMs(91); |
796 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))); | 799 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))); |
797 WaitForPendingRead(); | 800 WaitForPendingRead(); |
798 SatisfyPendingReadWithEndOfStream(); | 801 SatisfyPendingReadWithEndOfStream(); |
799 | 802 |
800 // If this wasn't background rendering mode, this would result in two frames | 803 // If this wasn't background rendering mode, this would result in two frames |
801 // being dropped, but since we set background render to true, none should be | 804 // being dropped, but since we set background render to true, none should be |
802 // reported | 805 // reported |
803 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped); | 806 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped); |
804 EXPECT_EQ(4u, last_pipeline_statistics_.video_frames_decoded); | 807 EXPECT_EQ(4u, last_pipeline_statistics.video_frames_decoded); |
805 EXPECT_EQ(460800, last_pipeline_statistics_.video_memory_usage); | 808 EXPECT_EQ(460800, last_pipeline_statistics.video_memory_usage); |
806 | 809 |
807 AdvanceTimeInMs(30); | 810 AdvanceTimeInMs(30); |
808 WaitForEnded(); | 811 WaitForEnded(); |
809 Destroy(); | 812 Destroy(); |
810 } | 813 } |
811 | 814 |
812 TEST_F(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) { | 815 TEST_F(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) { |
813 Initialize(); | 816 Initialize(); |
814 QueueFrames("0 30 60 90"); | 817 QueueFrames("0 30 60 90"); |
815 | 818 |
816 WaitableMessageLoopEvent event; | 819 WaitableMessageLoopEvent event; |
817 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 820 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
818 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 821 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
819 .WillOnce(RunClosure(event.GetClosure())); | 822 .WillOnce(RunClosure(event.GetClosure())); |
| 823 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
820 StartPlayingFrom(0); | 824 StartPlayingFrom(0); |
821 event.RunAndWait(); | 825 event.RunAndWait(); |
822 | 826 |
823 // Cycle ticking so that we get a non-null reference time. | 827 // Cycle ticking so that we get a non-null reference time. |
824 time_source_.StartTicking(); | 828 time_source_.StartTicking(); |
825 time_source_.StopTicking(); | 829 time_source_.StopTicking(); |
826 | 830 |
827 // Flush and simulate a seek past EOS, where some error prevents the decoder | 831 // Flush and simulate a seek past EOS, where some error prevents the decoder |
828 // from returning any frames. | 832 // from returning any frames. |
829 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)); | 833 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); |
830 Flush(); | 834 Flush(); |
831 | 835 |
832 StartPlayingFrom(200); | 836 StartPlayingFrom(200); |
833 WaitForPendingRead(); | 837 WaitForPendingRead(); |
834 SatisfyPendingReadWithEndOfStream(); | 838 SatisfyPendingReadWithEndOfStream(); |
835 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 839 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
836 WaitForEnded(); | 840 WaitForEnded(); |
837 Destroy(); | 841 Destroy(); |
838 } | 842 } |
839 | 843 |
840 TEST_F(VideoRendererImplTest, FramesAreNotExpiredDuringPreroll) { | 844 TEST_F(VideoRendererImplTest, FramesAreNotExpiredDuringPreroll) { |
841 Initialize(); | 845 Initialize(); |
842 // !CanReadWithoutStalling() puts the renderer in state BUFFERING_HAVE_ENOUGH | 846 // !CanReadWithoutStalling() puts the renderer in state BUFFERING_HAVE_ENOUGH |
843 // after the first frame. | 847 // after the first frame. |
844 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 848 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
845 // Set background rendering to simulate the first couple of Render() calls | 849 // Set background rendering to simulate the first couple of Render() calls |
846 // by VFC. | 850 // by VFC. |
847 null_video_sink_->set_background_render(true); | 851 null_video_sink_->set_background_render(true); |
848 QueueFrames("0 10 20"); | 852 QueueFrames("0 10 20"); |
849 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 853 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
850 .Times(testing::AtMost(1)); | 854 .Times(testing::AtMost(1)); |
851 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 855 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 856 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
852 StartPlayingFrom(0); | 857 StartPlayingFrom(0); |
853 | 858 |
854 renderer_->OnTimeStateChanged(true); | 859 renderer_->OnTimeStateChanged(true); |
855 time_source_.StartTicking(); | 860 time_source_.StartTicking(); |
856 | 861 |
857 WaitableMessageLoopEvent event; | 862 WaitableMessageLoopEvent event; |
858 // Frame "10" should not have been expired. | 863 // Frame "10" should not have been expired. |
859 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))) | 864 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))) |
860 .WillOnce(RunClosure(event.GetClosure())); | 865 .WillOnce(RunClosure(event.GetClosure())); |
861 AdvanceTimeInMs(10); | 866 AdvanceTimeInMs(10); |
(...skipping 12 matching lines...) Expand all Loading... |
874 } | 879 } |
875 | 880 |
876 protected: | 881 protected: |
877 std::vector<base::Closure> frame_ready_cbs_; | 882 std::vector<base::Closure> frame_ready_cbs_; |
878 }; | 883 }; |
879 | 884 |
880 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) { | 885 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) { |
881 Initialize(); | 886 Initialize(); |
882 QueueFrames("0 10 20 30"); | 887 QueueFrames("0 10 20 30"); |
883 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 888 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
884 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 889 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 890 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
885 StartPlayingFrom(0); | 891 StartPlayingFrom(0); |
886 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 892 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
887 | 893 |
888 uint32_t frame_ready_index = 0; | 894 uint32_t frame_ready_index = 0; |
889 while (frame_ready_index < frame_ready_cbs_.size()) { | 895 while (frame_ready_index < frame_ready_cbs_.size()) { |
890 frame_ready_cbs_[frame_ready_index++].Run(); | 896 frame_ready_cbs_[frame_ready_index++].Run(); |
891 message_loop_.RunUntilIdle(); | 897 message_loop_.RunUntilIdle(); |
892 } | 898 } |
893 Destroy(); | 899 Destroy(); |
894 } | 900 } |
895 | 901 |
896 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, SequenceTokenDiscardOneFrame) { | 902 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, SequenceTokenDiscardOneFrame) { |
897 Initialize(); | 903 Initialize(); |
898 QueueFrames("0 10 20 30"); | 904 QueueFrames("0 10 20 30"); |
899 StartPlayingFrom(0); | 905 StartPlayingFrom(0); |
900 Flush(); | 906 Flush(); |
901 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 907 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
902 // This frame will be discarded. | 908 // This frame will be discarded. |
903 frame_ready_cbs_.front().Run(); | 909 frame_ready_cbs_.front().Run(); |
904 Destroy(); | 910 Destroy(); |
905 } | 911 } |
906 | 912 |
907 } // namespace media | 913 } // namespace media |
OLD | NEW |