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

Side by Side Diff: media/renderers/video_renderer_impl_unittest.cc

Issue 1863373002: Fix underflow and av/sync issues in low delay and stall presence. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moar tests. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/renderers/video_renderer_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 time_ += base::TimeDelta::FromMilliseconds(time_ms); 272 time_ += base::TimeDelta::FromMilliseconds(time_ms);
273 time_source_.StopTicking(); 273 time_source_.StopTicking();
274 time_source_.SetMediaTime(time_); 274 time_source_.SetMediaTime(time_);
275 time_source_.StartTicking(); 275 time_source_.StartTicking();
276 } 276 }
277 277
278 bool has_ended() const { 278 bool has_ended() const {
279 return ended_event_.is_signaled(); 279 return ended_event_.is_signaled();
280 } 280 }
281 281
282 enum class UnderflowTestType { kNormal, kLowDelay, kCantReadWithoutStalling };
xhwang 2016/04/14 21:28:00 nit: use UPPER_CASE style for enums?
283 void BasicUnderflowTest(UnderflowTestType type) {
284 InitializeWithLowDelay(type == UnderflowTestType::kLowDelay);
285 if (type == UnderflowTestType::kCantReadWithoutStalling)
286 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
287
288 QueueFrames("0 30 60 90");
289
290 {
291 WaitableMessageLoopEvent event;
292 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
293 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
294 .WillOnce(RunClosure(event.GetClosure()));
295 StartPlayingFrom(0);
296 event.RunAndWait();
297 Mock::VerifyAndClearExpectations(&mock_cb_);
298 }
299
300 renderer_->OnTimeStateChanged(true);
301
302 // Advance time slightly, but enough to exceed the duration of the last
303 // frame.
304 // Frames should be dropped and we should NOT signal having nothing.
305 {
306 SCOPED_TRACE("Waiting for frame drops");
307 WaitableMessageLoopEvent event;
308
309 // Note: Starting the TimeSource will cause the old VideoRendererImpl to
310 // start rendering frames on its own thread, so the first frame may be
311 // received.
312 time_source_.StartTicking();
313 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
314
315 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
316 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
317 .WillOnce(RunClosure(event.GetClosure()));
318 AdvanceTimeInMs(91);
319
320 event.RunAndWait();
321 Mock::VerifyAndClearExpectations(&mock_cb_);
322 }
323
324 // Advance time more. Now we should signal having nothing. And put
325 // the last frame up for display.
326 {
327 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
328 WaitableMessageLoopEvent event;
329 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
330 .WillOnce(RunClosure(event.GetClosure()));
331 AdvanceTimeInMs(30);
332 event.RunAndWait();
333 Mock::VerifyAndClearExpectations(&mock_cb_);
334 }
335
336 // Receiving end of stream should signal having enough.
337 {
338 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
339 WaitableMessageLoopEvent event;
340 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
341 .WillOnce(RunClosure(event.GetClosure()));
342 SatisfyPendingReadWithEndOfStream();
343 event.RunAndWait();
344 }
345
346 WaitForEnded();
347 Destroy();
348 }
349
350 void UnderflowRecoveryTest(UnderflowTestType type) {
351 InitializeWithLowDelay(type == UnderflowTestType::kLowDelay);
352 if (type == UnderflowTestType::kCantReadWithoutStalling)
353 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
354
355 QueueFrames("0 20 40 60");
356 {
357 WaitableMessageLoopEvent event;
358 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
359 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
360 .WillOnce(RunClosure(event.GetClosure()));
361 StartPlayingFrom(0);
362 event.RunAndWait();
363 Mock::VerifyAndClearExpectations(&mock_cb_);
364 }
365
366 renderer_->OnTimeStateChanged(true);
367 time_source_.StartTicking();
368
369 // Advance time, this should cause have nothing to be signaled.
370 {
371 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
372 WaitableMessageLoopEvent event;
373 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
374 .WillOnce(RunClosure(event.GetClosure()));
375 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1);
376 AdvanceTimeInMs(20);
377 event.RunAndWait();
378 Mock::VerifyAndClearExpectations(&mock_cb_);
379 }
380
381 AdvanceTimeInMs(59);
382 EXPECT_EQ(3u, renderer_->frames_queued_for_testing());
383 time_source_.StopTicking();
384 renderer_->OnTimeStateChanged(false);
385 EXPECT_EQ(0u, renderer_->frames_queued_for_testing());
386 ASSERT_TRUE(IsReadPending());
387
388 // Queue some frames, satisfy reads, and make sure expired frames are gone
389 // when the renderer paints the first frame.
390 {
391 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
392 WaitableMessageLoopEvent event;
393 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1);
394 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
395 .WillOnce(RunClosure(event.GetClosure()));
396 if (type == UnderflowTestType::kNormal)
397 QueueFrames("80 100 120 140 160");
398 else
399 QueueFrames("40 60 80");
400 SatisfyPendingRead();
401 event.RunAndWait();
402 }
403
404 Destroy();
405 }
406
282 protected: 407 protected:
283 // Fixture members. 408 // Fixture members.
284 scoped_ptr<VideoRendererImpl> renderer_; 409 scoped_ptr<VideoRendererImpl> renderer_;
285 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. 410 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
286 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. 411 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|.
287 NiceMock<MockDemuxerStream> demuxer_stream_; 412 NiceMock<MockDemuxerStream> demuxer_stream_;
288 413
289 // Use StrictMock<T> to catch missing/extra callbacks. 414 // Use StrictMock<T> to catch missing/extra callbacks.
290 class MockCB { 415 class MockCB {
291 public: 416 public:
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 661
537 Destroy(); 662 Destroy();
538 } 663 }
539 664
540 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { 665 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
541 InitializeRenderer(false, false); 666 InitializeRenderer(false, false);
542 Destroy(); 667 Destroy();
543 } 668 }
544 669
545 TEST_F(VideoRendererImplTest, Underflow) { 670 TEST_F(VideoRendererImplTest, Underflow) {
546 Initialize(); 671 BasicUnderflowTest(UnderflowTestType::kNormal);
547 QueueFrames("0 30 60 90"); 672 }
548 673
549 { 674 TEST_F(VideoRendererImplTest, Underflow_LowDelay) {
550 WaitableMessageLoopEvent event; 675 BasicUnderflowTest(UnderflowTestType::kLowDelay);
551 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); 676 }
552 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
553 .WillOnce(RunClosure(event.GetClosure()));
554 StartPlayingFrom(0);
555 event.RunAndWait();
556 Mock::VerifyAndClearExpectations(&mock_cb_);
557 }
558 677
559 renderer_->OnTimeStateChanged(true); 678 TEST_F(VideoRendererImplTest, Underflow_CantReadWithoutStalling) {
679 BasicUnderflowTest(UnderflowTestType::kCantReadWithoutStalling);
680 }
560 681
561 // Advance time slightly, but enough to exceed the duration of the last frame. 682 TEST_F(VideoRendererImplTest, UnderflowRecovery) {
562 // Frames should be dropped and we should NOT signal having nothing. 683 UnderflowRecoveryTest(UnderflowTestType::kNormal);
563 { 684 }
564 SCOPED_TRACE("Waiting for frame drops");
565 WaitableMessageLoopEvent event;
566 685
567 // Note: Starting the TimeSource will cause the old VideoRendererImpl to 686 TEST_F(VideoRendererImplTest, UnderflowRecovery_LowDelay) {
568 // start rendering frames on its own thread, so the first frame may be 687 UnderflowRecoveryTest(UnderflowTestType::kLowDelay);
569 // received. 688 }
570 time_source_.StartTicking();
571 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
572 689
573 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); 690 TEST_F(VideoRendererImplTest, UnderflowRecovery_CantReadWithoutStalling) {
574 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) 691 UnderflowRecoveryTest(UnderflowTestType::kCantReadWithoutStalling);
575 .WillOnce(RunClosure(event.GetClosure()));
576 AdvanceTimeInMs(91);
577
578 event.RunAndWait();
579 Mock::VerifyAndClearExpectations(&mock_cb_);
580 }
581
582 // Advance time more. Now we should signal having nothing. And put
583 // the last frame up for display.
584 {
585 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
586 WaitableMessageLoopEvent event;
587 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
588 .WillOnce(RunClosure(event.GetClosure()));
589 AdvanceTimeInMs(30);
590 event.RunAndWait();
591 Mock::VerifyAndClearExpectations(&mock_cb_);
592 }
593
594 // Receiving end of stream should signal having enough.
595 {
596 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
597 WaitableMessageLoopEvent event;
598 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
599 .WillOnce(RunClosure(event.GetClosure()));
600 SatisfyPendingReadWithEndOfStream();
601 event.RunAndWait();
602 }
603
604 WaitForEnded();
605 Destroy();
606 } 692 }
607 693
608 // Verifies that the sink is stopped after rendering the first frame if 694 // Verifies that the sink is stopped after rendering the first frame if
609 // playback hasn't started. 695 // playback hasn't started.
610 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { 696 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
611 InitializeWithLowDelay(true); 697 InitializeWithLowDelay(true);
612 QueueFrames("0"); 698 QueueFrames("0");
613 699
614 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); 700 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
615 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); 701 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 QueueFrames("0 10 20 30"); 888 QueueFrames("0 10 20 30");
803 StartPlayingFrom(0); 889 StartPlayingFrom(0);
804 Flush(); 890 Flush();
805 ASSERT_EQ(1u, frame_ready_cbs_.size()); 891 ASSERT_EQ(1u, frame_ready_cbs_.size());
806 // This frame will be discarded. 892 // This frame will be discarded.
807 frame_ready_cbs_.front().Run(); 893 frame_ready_cbs_.front().Run();
808 Destroy(); 894 Destroy();
809 } 895 }
810 896
811 } // namespace media 897 } // namespace media
OLDNEW
« no previous file with comments | « media/renderers/video_renderer_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698