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

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: Clarified comment. 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 {
283 NORMAL,
284 LOW_DELAY,
285 CANT_READ_WITHOUT_STALLING
286 };
287 void BasicUnderflowTest(UnderflowTestType type) {
288 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY);
289 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING)
290 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
291
292 QueueFrames("0 30 60 90");
293
294 {
295 WaitableMessageLoopEvent event;
296 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
297 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
298 .WillOnce(RunClosure(event.GetClosure()));
299 StartPlayingFrom(0);
300 event.RunAndWait();
301 Mock::VerifyAndClearExpectations(&mock_cb_);
302 }
303
304 renderer_->OnTimeStateChanged(true);
305
306 // Advance time slightly, but enough to exceed the duration of the last
307 // frame.
308 // Frames should be dropped and we should NOT signal having nothing.
309 {
310 SCOPED_TRACE("Waiting for frame drops");
311 WaitableMessageLoopEvent event;
312
313 // Note: Starting the TimeSource will cause the old VideoRendererImpl to
314 // start rendering frames on its own thread, so the first frame may be
315 // received.
316 time_source_.StartTicking();
317 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
318
319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
320 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
321 .WillOnce(RunClosure(event.GetClosure()));
322 AdvanceTimeInMs(91);
323
324 event.RunAndWait();
325 Mock::VerifyAndClearExpectations(&mock_cb_);
326 }
327
328 // Advance time more. Now we should signal having nothing. And put
329 // the last frame up for display.
330 {
331 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
332 WaitableMessageLoopEvent event;
333 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
334 .WillOnce(RunClosure(event.GetClosure()));
335 AdvanceTimeInMs(30);
336 event.RunAndWait();
337 Mock::VerifyAndClearExpectations(&mock_cb_);
338 }
339
340 // Receiving end of stream should signal having enough.
341 {
342 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
343 WaitableMessageLoopEvent event;
344 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
345 .WillOnce(RunClosure(event.GetClosure()));
346 SatisfyPendingReadWithEndOfStream();
347 event.RunAndWait();
348 }
349
350 WaitForEnded();
351 Destroy();
352 }
353
354 void UnderflowRecoveryTest(UnderflowTestType type) {
355 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY);
356 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING)
357 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
358
359 QueueFrames("0 20 40 60");
360 {
361 WaitableMessageLoopEvent event;
362 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
363 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
364 .WillOnce(RunClosure(event.GetClosure()));
365 StartPlayingFrom(0);
366 event.RunAndWait();
367 Mock::VerifyAndClearExpectations(&mock_cb_);
368 }
369
370 renderer_->OnTimeStateChanged(true);
371 time_source_.StartTicking();
372
373 // Advance time, this should cause have nothing to be signaled.
374 {
375 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
376 WaitableMessageLoopEvent event;
377 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
378 .WillOnce(RunClosure(event.GetClosure()));
379 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1);
380 AdvanceTimeInMs(20);
381 event.RunAndWait();
382 Mock::VerifyAndClearExpectations(&mock_cb_);
383 }
384
385 AdvanceTimeInMs(59);
386 EXPECT_EQ(3u, renderer_->frames_queued_for_testing());
387 time_source_.StopTicking();
388 renderer_->OnTimeStateChanged(false);
389 EXPECT_EQ(0u, renderer_->frames_queued_for_testing());
390 ASSERT_TRUE(IsReadPending());
391
392 // Queue some frames, satisfy reads, and make sure expired frames are gone
393 // when the renderer paints the first frame.
394 {
395 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
396 WaitableMessageLoopEvent event;
397 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1);
398 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
399 .WillOnce(RunClosure(event.GetClosure()));
400 if (type == UnderflowTestType::NORMAL)
401 QueueFrames("80 100 120 140 160");
402 else
403 QueueFrames("40 60 80");
404 SatisfyPendingRead();
405 event.RunAndWait();
406 }
407
408 Destroy();
409 }
410
282 protected: 411 protected:
283 // Fixture members. 412 // Fixture members.
284 scoped_ptr<VideoRendererImpl> renderer_; 413 scoped_ptr<VideoRendererImpl> renderer_;
285 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. 414 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
286 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. 415 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|.
287 NiceMock<MockDemuxerStream> demuxer_stream_; 416 NiceMock<MockDemuxerStream> demuxer_stream_;
288 417
289 // Use StrictMock<T> to catch missing/extra callbacks. 418 // Use StrictMock<T> to catch missing/extra callbacks.
290 class MockCB { 419 class MockCB {
291 public: 420 public:
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 665
537 Destroy(); 666 Destroy();
538 } 667 }
539 668
540 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { 669 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
541 InitializeRenderer(false, false); 670 InitializeRenderer(false, false);
542 Destroy(); 671 Destroy();
543 } 672 }
544 673
545 TEST_F(VideoRendererImplTest, Underflow) { 674 TEST_F(VideoRendererImplTest, Underflow) {
546 Initialize(); 675 BasicUnderflowTest(UnderflowTestType::NORMAL);
547 QueueFrames("0 30 60 90"); 676 }
548 677
549 { 678 TEST_F(VideoRendererImplTest, Underflow_LowDelay) {
550 WaitableMessageLoopEvent event; 679 BasicUnderflowTest(UnderflowTestType::LOW_DELAY);
551 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); 680 }
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 681
559 renderer_->OnTimeStateChanged(true); 682 TEST_F(VideoRendererImplTest, Underflow_CantReadWithoutStalling) {
683 BasicUnderflowTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING);
684 }
560 685
561 // Advance time slightly, but enough to exceed the duration of the last frame. 686 TEST_F(VideoRendererImplTest, UnderflowRecovery) {
562 // Frames should be dropped and we should NOT signal having nothing. 687 UnderflowRecoveryTest(UnderflowTestType::NORMAL);
563 { 688 }
564 SCOPED_TRACE("Waiting for frame drops");
565 WaitableMessageLoopEvent event;
566 689
567 // Note: Starting the TimeSource will cause the old VideoRendererImpl to 690 TEST_F(VideoRendererImplTest, UnderflowRecovery_LowDelay) {
568 // start rendering frames on its own thread, so the first frame may be 691 UnderflowRecoveryTest(UnderflowTestType::LOW_DELAY);
569 // received. 692 }
570 time_source_.StartTicking();
571 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
572 693
573 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); 694 TEST_F(VideoRendererImplTest, UnderflowRecovery_CantReadWithoutStalling) {
574 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) 695 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING);
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 } 696 }
607 697
608 // Verifies that the sink is stopped after rendering the first frame if 698 // Verifies that the sink is stopped after rendering the first frame if
609 // playback hasn't started. 699 // playback hasn't started.
610 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { 700 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
611 InitializeWithLowDelay(true); 701 InitializeWithLowDelay(true);
612 QueueFrames("0"); 702 QueueFrames("0");
613 703
614 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); 704 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
615 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); 705 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"); 892 QueueFrames("0 10 20 30");
803 StartPlayingFrom(0); 893 StartPlayingFrom(0);
804 Flush(); 894 Flush();
805 ASSERT_EQ(1u, frame_ready_cbs_.size()); 895 ASSERT_EQ(1u, frame_ready_cbs_.size());
806 // This frame will be discarded. 896 // This frame will be discarded.
807 frame_ready_cbs_.front().Run(); 897 frame_ready_cbs_.front().Run();
808 Destroy(); 898 Destroy();
809 } 899 }
810 900
811 } // namespace media 901 } // 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