Port Chromium's blink_tests target to GN.
[chromium-blink-merge.git] / media / renderers / video_renderer_impl_unittest.cc
blob18a0f77dfcf9b0170beb4f5b417514645ecfadca
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.
5 #include <utility>
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/callback_helpers.h"
10 #include "base/debug/stack_trace.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/synchronization/lock.h"
17 #include "base/test/simple_test_tick_clock.h"
18 #include "media/base/data_buffer.h"
19 #include "media/base/gmock_callback_support.h"
20 #include "media/base/limits.h"
21 #include "media/base/mock_filters.h"
22 #include "media/base/null_video_sink.h"
23 #include "media/base/test_helpers.h"
24 #include "media/base/video_frame.h"
25 #include "media/renderers/video_renderer_impl.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using ::testing::_;
29 using ::testing::AnyNumber;
30 using ::testing::Invoke;
31 using ::testing::Mock;
32 using ::testing::NiceMock;
33 using ::testing::Return;
34 using ::testing::SaveArg;
35 using ::testing::StrictMock;
37 namespace media {
39 ACTION_P(RunClosure, closure) {
40 closure.Run();
43 MATCHER_P(HasTimestamp, ms, "") {
44 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds();
45 return arg->timestamp().InMilliseconds() == ms;
48 class VideoRendererImplTest : public testing::TestWithParam<bool> {
49 public:
50 VideoRendererImplTest()
51 : tick_clock_(new base::SimpleTestTickClock()),
52 decoder_(new MockVideoDecoder()),
53 demuxer_stream_(DemuxerStream::VIDEO) {
54 ScopedVector<VideoDecoder> decoders;
55 decoders.push_back(decoder_);
57 null_video_sink_.reset(new NullVideoSink(
58 false, base::TimeDelta::FromSecondsD(1.0 / 60),
59 base::Bind(&MockCB::FrameReceived, base::Unretained(&mock_cb_)),
60 message_loop_.task_runner()));
62 renderer_.reset(new VideoRendererImpl(
63 message_loop_.message_loop_proxy(), null_video_sink_.get(),
64 decoders.Pass(), true, new MediaLog()));
65 if (!GetParam())
66 renderer_->disable_new_video_renderer_for_testing();
67 renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
68 null_video_sink_->set_tick_clock_for_testing(tick_clock_);
70 // Start wallclock time at a non-zero value.
71 AdvanceWallclockTimeInMs(12345);
73 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
75 // We expect these to be called but we don't care how/when.
76 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
77 RunCallback<0>(DemuxerStream::kOk,
78 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
81 virtual ~VideoRendererImplTest() {}
83 void Initialize() {
84 InitializeWithLowDelay(false);
87 void InitializeWithLowDelay(bool low_delay) {
88 // Monitor decodes from the decoder.
89 EXPECT_CALL(*decoder_, Decode(_, _))
90 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::DecodeRequested));
92 EXPECT_CALL(*decoder_, Reset(_))
93 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested));
95 // Initialize, we shouldn't have any reads.
96 InitializeRenderer(PIPELINE_OK, low_delay);
99 void InitializeRenderer(PipelineStatus expected, bool low_delay) {
100 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected));
101 WaitableMessageLoopEvent event;
102 CallInitialize(event.GetPipelineStatusCB(), low_delay, expected);
103 event.RunAndWaitForStatus(expected);
106 void CallInitialize(const PipelineStatusCB& status_cb,
107 bool low_delay,
108 PipelineStatus decoder_status) {
109 if (low_delay)
110 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE);
111 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)).WillOnce(
112 DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(decoder_status)));
113 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
114 renderer_->Initialize(
115 &demuxer_stream_, status_cb, media::SetDecryptorReadyCB(),
116 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate,
117 base::Unretained(this)),
118 base::Bind(&StrictMock<MockCB>::BufferingStateChange,
119 base::Unretained(&mock_cb_)),
120 ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(),
121 base::Bind(&VideoRendererImplTest::GetWallClockTime,
122 base::Unretained(this)),
123 base::Bind(&VideoRendererImplTest::OnWaitingForDecryptionKey,
124 base::Unretained(this)));
127 void StartPlayingFrom(int milliseconds) {
128 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds));
129 renderer_->StartPlayingFrom(
130 base::TimeDelta::FromMilliseconds(milliseconds));
131 message_loop_.RunUntilIdle();
134 void Flush() {
135 SCOPED_TRACE("Flush()");
136 WaitableMessageLoopEvent event;
137 renderer_->Flush(event.GetClosure());
138 event.RunAndWait();
141 void Destroy() {
142 SCOPED_TRACE("Destroy()");
143 renderer_.reset();
144 message_loop_.RunUntilIdle();
147 // Parses a string representation of video frames and generates corresponding
148 // VideoFrame objects in |decode_results_|.
150 // Syntax:
151 // nn - Queue a decoder buffer with timestamp nn * 1000us
152 // abort - Queue an aborted read
153 // error - Queue a decoder error
155 // Examples:
156 // A clip that is four frames long: "0 10 20 30"
157 // A clip that has a decode error: "60 70 error"
158 void QueueFrames(const std::string& str) {
159 std::vector<std::string> tokens;
160 base::SplitString(str, ' ', &tokens);
161 for (size_t i = 0; i < tokens.size(); ++i) {
162 if (tokens[i] == "abort") {
163 scoped_refptr<VideoFrame> null_frame;
164 decode_results_.push_back(
165 std::make_pair(VideoDecoder::kAborted, null_frame));
166 continue;
169 if (tokens[i] == "error") {
170 scoped_refptr<VideoFrame> null_frame;
171 decode_results_.push_back(
172 std::make_pair(VideoDecoder::kDecodeError, null_frame));
173 continue;
176 int timestamp_in_ms = 0;
177 if (base::StringToInt(tokens[i], &timestamp_in_ms)) {
178 gfx::Size natural_size = TestVideoConfig::NormalCodedSize();
179 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
180 VideoFrame::YV12,
181 natural_size,
182 gfx::Rect(natural_size),
183 natural_size,
184 base::TimeDelta::FromMilliseconds(timestamp_in_ms));
185 decode_results_.push_back(std::make_pair(VideoDecoder::kOk, frame));
186 continue;
189 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i];
193 bool IsReadPending() {
194 return !decode_cb_.is_null();
197 void WaitForError(PipelineStatus expected) {
198 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected));
199 error_event_.RunAndWaitForStatus(expected);
202 void WaitForEnded() {
203 SCOPED_TRACE("WaitForEnded()");
204 ended_event_.RunAndWait();
207 void WaitForPendingRead() {
208 SCOPED_TRACE("WaitForPendingRead()");
209 if (!decode_cb_.is_null())
210 return;
212 DCHECK(wait_for_pending_decode_cb_.is_null());
214 WaitableMessageLoopEvent event;
215 wait_for_pending_decode_cb_ = event.GetClosure();
216 event.RunAndWait();
218 DCHECK(!decode_cb_.is_null());
219 DCHECK(wait_for_pending_decode_cb_.is_null());
222 void SatisfyPendingRead() {
223 CHECK(!decode_cb_.is_null());
224 CHECK(!decode_results_.empty());
226 // Post tasks for OutputCB and DecodeCB.
227 scoped_refptr<VideoFrame> frame = decode_results_.front().second;
228 if (frame.get())
229 message_loop_.PostTask(FROM_HERE, base::Bind(output_cb_, frame));
230 message_loop_.PostTask(
231 FROM_HERE, base::Bind(base::ResetAndReturn(&decode_cb_),
232 decode_results_.front().first));
233 decode_results_.pop_front();
236 void SatisfyPendingReadWithEndOfStream() {
237 DCHECK(!decode_cb_.is_null());
239 // Return EOS buffer to trigger EOS frame.
240 EXPECT_CALL(demuxer_stream_, Read(_))
241 .WillOnce(RunCallback<0>(DemuxerStream::kOk,
242 DecoderBuffer::CreateEOSBuffer()));
244 // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read().
245 message_loop_.PostTask(
246 FROM_HERE,
247 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
249 WaitForPendingRead();
251 message_loop_.PostTask(
252 FROM_HERE,
253 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
256 void AdvanceWallclockTimeInMs(int time_ms) {
257 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
258 base::AutoLock l(lock_);
259 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(time_ms));
262 void AdvanceTimeInMs(int time_ms) {
263 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
264 base::AutoLock l(lock_);
265 time_ += base::TimeDelta::FromMilliseconds(time_ms);
268 bool has_ended() const {
269 return ended_event_.is_signaled();
272 protected:
273 // Fixture members.
274 scoped_ptr<VideoRendererImpl> renderer_;
275 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
276 MockVideoDecoder* decoder_; // Owned by |renderer_|.
277 NiceMock<MockDemuxerStream> demuxer_stream_;
279 // Use StrictMock<T> to catch missing/extra callbacks.
280 class MockCB {
281 public:
282 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
283 MOCK_METHOD1(BufferingStateChange, void(BufferingState));
285 StrictMock<MockCB> mock_cb_;
287 // Must be destroyed before |renderer_| since they share |tick_clock_|.
288 scoped_ptr<NullVideoSink> null_video_sink_;
290 PipelineStatistics last_pipeline_statistics_;
292 private:
293 base::TimeTicks GetWallClockTime(base::TimeDelta time) {
294 base::AutoLock l(lock_);
295 return tick_clock_->NowTicks() + (time - time_);
298 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer,
299 const VideoDecoder::DecodeCB& decode_cb) {
300 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
301 CHECK(decode_cb_.is_null());
302 decode_cb_ = decode_cb;
304 // Wake up WaitForPendingRead() if needed.
305 if (!wait_for_pending_decode_cb_.is_null())
306 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run();
308 if (decode_results_.empty())
309 return;
311 SatisfyPendingRead();
314 void FlushRequested(const base::Closure& callback) {
315 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
316 decode_results_.clear();
317 if (!decode_cb_.is_null()) {
318 QueueFrames("abort");
319 SatisfyPendingRead();
322 message_loop_.PostTask(FROM_HERE, callback);
325 void OnStatisticsUpdate(const PipelineStatistics& stats) {
326 last_pipeline_statistics_ = stats;
329 MOCK_METHOD0(OnWaitingForDecryptionKey, void(void));
331 base::MessageLoop message_loop_;
333 // Used to protect |time_|.
334 base::Lock lock_;
335 base::TimeDelta time_;
337 // Used for satisfying reads.
338 VideoDecoder::OutputCB output_cb_;
339 VideoDecoder::DecodeCB decode_cb_;
340 base::TimeDelta next_frame_timestamp_;
342 WaitableMessageLoopEvent error_event_;
343 WaitableMessageLoopEvent ended_event_;
345 // Run during DecodeRequested() to unblock WaitForPendingRead().
346 base::Closure wait_for_pending_decode_cb_;
348 std::deque<std::pair<
349 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
351 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
354 TEST_P(VideoRendererImplTest, DoNothing) {
355 // Test that creation and deletion doesn't depend on calls to Initialize()
356 // and/or Destroy().
359 TEST_P(VideoRendererImplTest, DestroyWithoutInitialize) {
360 Destroy();
363 TEST_P(VideoRendererImplTest, Initialize) {
364 Initialize();
365 Destroy();
368 TEST_P(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
369 Initialize();
370 QueueFrames("0 10 20 30");
371 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
372 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
373 StartPlayingFrom(0);
374 Destroy();
377 TEST_P(VideoRendererImplTest, InitializeAndEndOfStream) {
378 Initialize();
379 StartPlayingFrom(0);
380 WaitForPendingRead();
382 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
383 WaitableMessageLoopEvent event;
384 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
385 .WillOnce(RunClosure(event.GetClosure()));
386 SatisfyPendingReadWithEndOfStream();
387 event.RunAndWait();
389 // Firing a time state changed to true should be ignored...
390 renderer_->OnTimeStateChanged(true);
391 EXPECT_FALSE(null_video_sink_->is_started());
392 Destroy();
395 TEST_P(VideoRendererImplTest, DestroyWhileInitializing) {
396 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK);
397 Destroy();
400 TEST_P(VideoRendererImplTest, DestroyWhileFlushing) {
401 Initialize();
402 QueueFrames("0 10 20 30");
403 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
404 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
405 StartPlayingFrom(0);
406 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING));
407 renderer_->Flush(NewExpectedClosure());
408 Destroy();
411 TEST_P(VideoRendererImplTest, Play) {
412 Initialize();
413 QueueFrames("0 10 20 30");
414 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
415 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
416 StartPlayingFrom(0);
417 Destroy();
420 TEST_P(VideoRendererImplTest, FlushWithNothingBuffered) {
421 Initialize();
422 StartPlayingFrom(0);
424 // We shouldn't expect a buffering state change since we never reached
425 // BUFFERING_HAVE_ENOUGH.
426 Flush();
427 Destroy();
430 TEST_P(VideoRendererImplTest, DecodeError_Playing) {
431 Initialize();
432 QueueFrames("0 10 20 30");
433 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
434 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
435 StartPlayingFrom(0);
436 renderer_->OnTimeStateChanged(true);
437 AdvanceTimeInMs(10);
439 QueueFrames("error");
440 SatisfyPendingRead();
441 WaitForError(PIPELINE_ERROR_DECODE);
442 Destroy();
445 TEST_P(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
446 Initialize();
447 QueueFrames("error");
448 StartPlayingFrom(0);
449 Destroy();
452 TEST_P(VideoRendererImplTest, StartPlayingFrom_Exact) {
453 Initialize();
454 QueueFrames("50 60 70 80 90");
456 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
457 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
458 StartPlayingFrom(60);
459 Destroy();
462 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
463 Initialize();
464 QueueFrames("50 60 70 80 90");
466 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50)));
467 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
468 StartPlayingFrom(59);
469 Destroy();
472 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
473 Initialize();
474 QueueFrames("50 60 70 80 90");
476 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
477 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
478 StartPlayingFrom(61);
479 Destroy();
482 TEST_P(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
483 // In low-delay mode only one frame is required to finish preroll.
484 InitializeWithLowDelay(true);
485 QueueFrames("0");
487 // Expect some amount of have enough/nothing due to only requiring one frame.
488 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
489 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
490 .Times(AnyNumber());
491 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
492 .Times(AnyNumber());
493 StartPlayingFrom(0);
495 QueueFrames("10");
496 SatisfyPendingRead();
498 renderer_->OnTimeStateChanged(true);
499 WaitableMessageLoopEvent event;
500 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)))
501 .WillOnce(RunClosure(event.GetClosure()));
502 AdvanceTimeInMs(10);
503 event.RunAndWait();
505 Destroy();
508 // Verify that a late decoder response doesn't break invariants in the renderer.
509 TEST_P(VideoRendererImplTest, DestroyDuringOutstandingRead) {
510 Initialize();
511 QueueFrames("0 10 20 30");
512 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
513 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
514 StartPlayingFrom(0);
516 // Check that there is an outstanding Read() request.
517 EXPECT_TRUE(IsReadPending());
519 Destroy();
522 TEST_P(VideoRendererImplTest, VideoDecoder_InitFailure) {
523 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED, false);
524 Destroy();
527 TEST_P(VideoRendererImplTest, Underflow) {
528 Initialize();
529 QueueFrames("0 30 60 90");
532 WaitableMessageLoopEvent event;
533 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
534 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
535 .WillOnce(RunClosure(event.GetClosure()));
536 StartPlayingFrom(0);
537 event.RunAndWait();
538 Mock::VerifyAndClearExpectations(&mock_cb_);
541 renderer_->OnTimeStateChanged(true);
543 // Advance time slightly, but enough to exceed the duration of the last frame.
544 // Frames should be dropped and we should NOT signal having nothing.
546 SCOPED_TRACE("Waiting for frame drops");
547 WaitableMessageLoopEvent event;
548 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30)))
549 .Times(0);
550 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)))
551 .Times(0);
552 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
553 .WillOnce(RunClosure(event.GetClosure()));
554 AdvanceTimeInMs(91);
556 event.RunAndWait();
557 Mock::VerifyAndClearExpectations(&mock_cb_);
560 // Advance time more. Now we should signal having nothing. And put
561 // the last frame up for display.
563 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
564 WaitableMessageLoopEvent event;
565 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
566 .WillOnce(RunClosure(event.GetClosure()));
567 AdvanceTimeInMs(30);
568 // The old rendering path needs wall clock time to increase too.
569 if (!GetParam())
570 AdvanceWallclockTimeInMs(30);
572 event.RunAndWait();
573 Mock::VerifyAndClearExpectations(&mock_cb_);
576 // Receiving end of stream should signal having enough.
578 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
579 WaitableMessageLoopEvent event;
580 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
581 .WillOnce(RunClosure(event.GetClosure()));
582 SatisfyPendingReadWithEndOfStream();
583 event.RunAndWait();
586 WaitForEnded();
587 Destroy();
590 // Verifies that the sink is stopped after rendering the first frame if
591 // playback hasn't started.
592 TEST_P(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
593 // This test is only for the new rendering path.
594 if (!GetParam())
595 return;
597 InitializeWithLowDelay(true);
598 QueueFrames("0");
600 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
601 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
604 SCOPED_TRACE("Waiting for sink to stop.");
605 WaitableMessageLoopEvent event;
607 null_video_sink_->set_background_render(true);
608 null_video_sink_->set_stop_cb(event.GetClosure());
609 StartPlayingFrom(0);
611 EXPECT_TRUE(IsReadPending());
612 SatisfyPendingReadWithEndOfStream();
614 event.RunAndWait();
617 EXPECT_FALSE(has_ended());
618 Destroy();
621 // Verifies that the sink is stopped after rendering the first frame if
622 // playback ha started.
623 TEST_P(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) {
624 // This test is only for the new rendering path.
625 if (!GetParam())
626 return;
628 InitializeWithLowDelay(true);
629 QueueFrames("0");
631 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
632 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
635 SCOPED_TRACE("Waiting for sink to stop.");
636 WaitableMessageLoopEvent event;
638 null_video_sink_->set_stop_cb(event.GetClosure());
639 StartPlayingFrom(0);
640 renderer_->OnTimeStateChanged(true);
642 EXPECT_TRUE(IsReadPending());
643 SatisfyPendingReadWithEndOfStream();
644 WaitForEnded();
646 renderer_->OnTimeStateChanged(false);
647 event.RunAndWait();
650 Destroy();
653 // Tests the case where the video started and received a single Render() call,
654 // then the video was put into the background.
655 TEST_P(VideoRendererImplTest, RenderingStartedThenStopped) {
656 // This test is only for the new rendering path.
657 if (!GetParam())
658 return;
660 Initialize();
661 QueueFrames("0 30 60 90");
663 // Start the sink and wait for the first callback. Set statistics to a non
664 // zero value, once we have some decoded frames they should be overwritten.
665 last_pipeline_statistics_.video_frames_dropped = 1;
667 WaitableMessageLoopEvent event;
668 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
669 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)))
670 .WillOnce(RunClosure(event.GetClosure()));
671 StartPlayingFrom(0);
672 event.RunAndWait();
673 Mock::VerifyAndClearExpectations(&mock_cb_);
674 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
677 renderer_->OnTimeStateChanged(true);
679 // Suspend all future callbacks and synthetically advance the media time,
680 // because this is a background render, we won't underflow by waiting until
681 // a pending read is ready.
682 null_video_sink_->set_background_render(true);
683 AdvanceTimeInMs(91);
684 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)));
685 WaitForPendingRead();
686 SatisfyPendingReadWithEndOfStream();
688 // If this wasn't background rendering mode, this would result in two frames
689 // being dropped, but since we set background render to true, none should be
690 // reported
691 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
692 EXPECT_EQ(4u, last_pipeline_statistics_.video_frames_decoded);
694 AdvanceTimeInMs(30);
695 WaitForEnded();
696 Destroy();
699 INSTANTIATE_TEST_CASE_P(OldVideoRenderer,
700 VideoRendererImplTest,
701 testing::Values(false));
702 INSTANTIATE_TEST_CASE_P(NewVideoRenderer,
703 VideoRendererImplTest,
704 testing::Values(true));
706 } // namespace media