media: Reland "Simplify {Audio|Video}Decoder initialization callback."
[chromium-blink-merge.git] / media / renderers / video_renderer_impl_unittest.cc
blob75c599e3d6b854170d74f55b01a209b13d68f752
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/base/wall_clock_time_source.h"
26 #include "media/renderers/video_renderer_impl.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using ::testing::_;
30 using ::testing::AnyNumber;
31 using ::testing::Invoke;
32 using ::testing::Mock;
33 using ::testing::NiceMock;
34 using ::testing::Return;
35 using ::testing::SaveArg;
36 using ::testing::StrictMock;
38 namespace media {
40 ACTION_P(RunClosure, closure) {
41 closure.Run();
44 MATCHER_P(HasTimestamp, ms, "") {
45 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds();
46 return arg->timestamp().InMilliseconds() == ms;
49 class VideoRendererImplTest : public testing::TestWithParam<bool> {
50 public:
51 VideoRendererImplTest()
52 : tick_clock_(new base::SimpleTestTickClock()),
53 decoder_(new MockVideoDecoder()),
54 demuxer_stream_(DemuxerStream::VIDEO) {
55 ScopedVector<VideoDecoder> decoders;
56 decoders.push_back(decoder_);
58 null_video_sink_.reset(new NullVideoSink(
59 false, base::TimeDelta::FromSecondsD(1.0 / 60),
60 base::Bind(&MockCB::FrameReceived, base::Unretained(&mock_cb_)),
61 message_loop_.task_runner()));
63 renderer_.reset(new VideoRendererImpl(message_loop_.message_loop_proxy(),
64 null_video_sink_.get(),
65 decoders.Pass(), true,
66 nullptr, // gpu_factories
67 new MediaLog()));
68 if (!GetParam())
69 renderer_->disable_new_video_renderer_for_testing();
70 renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
71 null_video_sink_->set_tick_clock_for_testing(tick_clock_);
72 time_source_.set_tick_clock_for_testing(tick_clock_);
74 // Start wallclock time at a non-zero value.
75 AdvanceWallclockTimeInMs(12345);
77 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
79 // We expect these to be called but we don't care how/when.
80 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
81 RunCallback<0>(DemuxerStream::kOk,
82 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
85 virtual ~VideoRendererImplTest() {}
87 void Initialize() {
88 InitializeWithLowDelay(false);
91 void InitializeWithLowDelay(bool low_delay) {
92 // Monitor decodes from the decoder.
93 EXPECT_CALL(*decoder_, Decode(_, _))
94 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::DecodeRequested));
96 EXPECT_CALL(*decoder_, Reset(_))
97 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested));
99 // Initialize, we shouldn't have any reads.
100 InitializeRenderer(low_delay, true);
103 void InitializeRenderer(bool low_delay, bool expect_to_success) {
104 SCOPED_TRACE(
105 base::StringPrintf("InitializeRenderer(%d)", expect_to_success));
106 WaitableMessageLoopEvent event;
107 CallInitialize(event.GetPipelineStatusCB(), low_delay, expect_to_success);
108 event.RunAndWaitForStatus(expect_to_success ? PIPELINE_OK
109 : DECODER_ERROR_NOT_SUPPORTED);
112 void CallInitialize(const PipelineStatusCB& status_cb,
113 bool low_delay,
114 bool expect_to_success) {
115 if (low_delay)
116 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE);
117 EXPECT_CALL(*decoder_, Initialize(_, _, _, _))
118 .WillOnce(
119 DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(expect_to_success)));
120 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
121 renderer_->Initialize(
122 &demuxer_stream_, status_cb, media::SetDecryptorReadyCB(),
123 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate,
124 base::Unretained(this)),
125 base::Bind(&StrictMock<MockCB>::BufferingStateChange,
126 base::Unretained(&mock_cb_)),
127 ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(),
128 base::Bind(&WallClockTimeSource::GetWallClockTimes,
129 base::Unretained(&time_source_)),
130 base::Bind(&VideoRendererImplTest::OnWaitingForDecryptionKey,
131 base::Unretained(this)));
134 void StartPlayingFrom(int milliseconds) {
135 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds));
136 const base::TimeDelta media_time =
137 base::TimeDelta::FromMilliseconds(milliseconds);
138 time_source_.SetMediaTime(media_time);
139 renderer_->StartPlayingFrom(media_time);
140 message_loop_.RunUntilIdle();
143 void Flush() {
144 SCOPED_TRACE("Flush()");
145 WaitableMessageLoopEvent event;
146 renderer_->Flush(event.GetClosure());
147 event.RunAndWait();
150 void Destroy() {
151 SCOPED_TRACE("Destroy()");
152 renderer_.reset();
153 message_loop_.RunUntilIdle();
156 // Parses a string representation of video frames and generates corresponding
157 // VideoFrame objects in |decode_results_|.
159 // Syntax:
160 // nn - Queue a decoder buffer with timestamp nn * 1000us
161 // abort - Queue an aborted read
162 // error - Queue a decoder error
164 // Examples:
165 // A clip that is four frames long: "0 10 20 30"
166 // A clip that has a decode error: "60 70 error"
167 void QueueFrames(const std::string& str) {
168 std::vector<std::string> tokens;
169 base::SplitString(str, ' ', &tokens);
170 for (size_t i = 0; i < tokens.size(); ++i) {
171 if (tokens[i] == "abort") {
172 scoped_refptr<VideoFrame> null_frame;
173 decode_results_.push_back(
174 std::make_pair(VideoDecoder::kAborted, null_frame));
175 continue;
178 if (tokens[i] == "error") {
179 scoped_refptr<VideoFrame> null_frame;
180 decode_results_.push_back(
181 std::make_pair(VideoDecoder::kDecodeError, null_frame));
182 continue;
185 int timestamp_in_ms = 0;
186 if (base::StringToInt(tokens[i], &timestamp_in_ms)) {
187 gfx::Size natural_size = TestVideoConfig::NormalCodedSize();
188 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
189 VideoFrame::YV12,
190 natural_size,
191 gfx::Rect(natural_size),
192 natural_size,
193 base::TimeDelta::FromMilliseconds(timestamp_in_ms));
194 decode_results_.push_back(std::make_pair(VideoDecoder::kOk, frame));
195 continue;
198 CHECK(false) << "Unrecognized decoder buffer token: " << tokens[i];
202 bool IsReadPending() {
203 return !decode_cb_.is_null();
206 void WaitForError(PipelineStatus expected) {
207 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected));
208 error_event_.RunAndWaitForStatus(expected);
211 void WaitForEnded() {
212 SCOPED_TRACE("WaitForEnded()");
213 ended_event_.RunAndWait();
216 void WaitForPendingRead() {
217 SCOPED_TRACE("WaitForPendingRead()");
218 if (!decode_cb_.is_null())
219 return;
221 DCHECK(wait_for_pending_decode_cb_.is_null());
223 WaitableMessageLoopEvent event;
224 wait_for_pending_decode_cb_ = event.GetClosure();
225 event.RunAndWait();
227 DCHECK(!decode_cb_.is_null());
228 DCHECK(wait_for_pending_decode_cb_.is_null());
231 void SatisfyPendingRead() {
232 CHECK(!decode_cb_.is_null());
233 CHECK(!decode_results_.empty());
235 // Post tasks for OutputCB and DecodeCB.
236 scoped_refptr<VideoFrame> frame = decode_results_.front().second;
237 if (frame.get())
238 message_loop_.PostTask(FROM_HERE, base::Bind(output_cb_, frame));
239 message_loop_.PostTask(
240 FROM_HERE, base::Bind(base::ResetAndReturn(&decode_cb_),
241 decode_results_.front().first));
242 decode_results_.pop_front();
245 void SatisfyPendingReadWithEndOfStream() {
246 DCHECK(!decode_cb_.is_null());
248 // Return EOS buffer to trigger EOS frame.
249 EXPECT_CALL(demuxer_stream_, Read(_))
250 .WillOnce(RunCallback<0>(DemuxerStream::kOk,
251 DecoderBuffer::CreateEOSBuffer()));
253 // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read().
254 message_loop_.PostTask(
255 FROM_HERE,
256 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
258 WaitForPendingRead();
260 message_loop_.PostTask(
261 FROM_HERE,
262 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
265 void AdvanceWallclockTimeInMs(int time_ms) {
266 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
267 base::AutoLock l(lock_);
268 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(time_ms));
271 void AdvanceTimeInMs(int time_ms) {
272 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
273 base::AutoLock l(lock_);
274 time_ += base::TimeDelta::FromMilliseconds(time_ms);
275 time_source_.StopTicking();
276 time_source_.SetMediaTime(time_);
277 time_source_.StartTicking();
280 bool has_ended() const {
281 return ended_event_.is_signaled();
284 protected:
285 // Fixture members.
286 scoped_ptr<VideoRendererImpl> renderer_;
287 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
288 MockVideoDecoder* decoder_; // Owned by |renderer_|.
289 NiceMock<MockDemuxerStream> demuxer_stream_;
291 // Use StrictMock<T> to catch missing/extra callbacks.
292 class MockCB {
293 public:
294 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
295 MOCK_METHOD1(BufferingStateChange, void(BufferingState));
297 StrictMock<MockCB> mock_cb_;
299 // Must be destroyed before |renderer_| since they share |tick_clock_|.
300 scoped_ptr<NullVideoSink> null_video_sink_;
302 PipelineStatistics last_pipeline_statistics_;
304 WallClockTimeSource time_source_;
306 private:
307 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer,
308 const VideoDecoder::DecodeCB& decode_cb) {
309 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
310 CHECK(decode_cb_.is_null());
311 decode_cb_ = decode_cb;
313 // Wake up WaitForPendingRead() if needed.
314 if (!wait_for_pending_decode_cb_.is_null())
315 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run();
317 if (decode_results_.empty())
318 return;
320 SatisfyPendingRead();
323 void FlushRequested(const base::Closure& callback) {
324 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
325 decode_results_.clear();
326 if (!decode_cb_.is_null()) {
327 QueueFrames("abort");
328 SatisfyPendingRead();
331 message_loop_.PostTask(FROM_HERE, callback);
334 void OnStatisticsUpdate(const PipelineStatistics& stats) {
335 last_pipeline_statistics_ = stats;
338 MOCK_METHOD0(OnWaitingForDecryptionKey, void(void));
340 base::MessageLoop message_loop_;
342 // Used to protect |time_|.
343 base::Lock lock_;
344 base::TimeDelta time_;
346 // Used for satisfying reads.
347 VideoDecoder::OutputCB output_cb_;
348 VideoDecoder::DecodeCB decode_cb_;
349 base::TimeDelta next_frame_timestamp_;
351 WaitableMessageLoopEvent error_event_;
352 WaitableMessageLoopEvent ended_event_;
354 // Run during DecodeRequested() to unblock WaitForPendingRead().
355 base::Closure wait_for_pending_decode_cb_;
357 std::deque<std::pair<
358 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
360 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
363 TEST_P(VideoRendererImplTest, DoNothing) {
364 // Test that creation and deletion doesn't depend on calls to Initialize()
365 // and/or Destroy().
368 TEST_P(VideoRendererImplTest, DestroyWithoutInitialize) {
369 Destroy();
372 TEST_P(VideoRendererImplTest, Initialize) {
373 Initialize();
374 Destroy();
377 TEST_P(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
378 Initialize();
379 QueueFrames("0 10 20 30");
380 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
381 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
382 StartPlayingFrom(0);
383 Destroy();
386 TEST_P(VideoRendererImplTest, InitializeAndEndOfStream) {
387 Initialize();
388 StartPlayingFrom(0);
389 WaitForPendingRead();
391 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
392 WaitableMessageLoopEvent event;
393 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
394 .WillOnce(RunClosure(event.GetClosure()));
395 SatisfyPendingReadWithEndOfStream();
396 event.RunAndWait();
398 // Firing a time state changed to true should be ignored...
399 renderer_->OnTimeStateChanged(true);
400 EXPECT_FALSE(null_video_sink_->is_started());
401 Destroy();
404 TEST_P(VideoRendererImplTest, DestroyWhileInitializing) {
405 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK);
406 Destroy();
409 TEST_P(VideoRendererImplTest, DestroyWhileFlushing) {
410 Initialize();
411 QueueFrames("0 10 20 30");
412 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
413 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
414 StartPlayingFrom(0);
415 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING));
416 renderer_->Flush(NewExpectedClosure());
417 Destroy();
420 TEST_P(VideoRendererImplTest, Play) {
421 Initialize();
422 QueueFrames("0 10 20 30");
423 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
424 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
425 StartPlayingFrom(0);
426 Destroy();
429 TEST_P(VideoRendererImplTest, FlushWithNothingBuffered) {
430 Initialize();
431 StartPlayingFrom(0);
433 // We shouldn't expect a buffering state change since we never reached
434 // BUFFERING_HAVE_ENOUGH.
435 Flush();
436 Destroy();
439 TEST_P(VideoRendererImplTest, DecodeError_Playing) {
440 Initialize();
441 QueueFrames("0 10 20 30");
442 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
443 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
444 StartPlayingFrom(0);
445 renderer_->OnTimeStateChanged(true);
446 time_source_.StartTicking();
447 AdvanceTimeInMs(10);
449 QueueFrames("error");
450 SatisfyPendingRead();
451 WaitForError(PIPELINE_ERROR_DECODE);
452 Destroy();
455 TEST_P(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
456 Initialize();
457 QueueFrames("error");
458 StartPlayingFrom(0);
459 Destroy();
462 TEST_P(VideoRendererImplTest, StartPlayingFrom_Exact) {
463 Initialize();
464 QueueFrames("50 60 70 80 90");
466 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
467 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
468 StartPlayingFrom(60);
469 Destroy();
472 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
473 Initialize();
474 QueueFrames("50 60 70 80 90");
476 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50)));
477 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
478 StartPlayingFrom(59);
479 Destroy();
482 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
483 Initialize();
484 QueueFrames("50 60 70 80 90");
486 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
487 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
488 StartPlayingFrom(61);
489 Destroy();
492 TEST_P(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
493 // In low-delay mode only one frame is required to finish preroll.
494 InitializeWithLowDelay(true);
495 QueueFrames("0");
497 // Expect some amount of have enough/nothing due to only requiring one frame.
498 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
499 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
500 .Times(AnyNumber());
501 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
502 .Times(AnyNumber());
503 StartPlayingFrom(0);
505 QueueFrames("10");
506 SatisfyPendingRead();
508 renderer_->OnTimeStateChanged(true);
509 time_source_.StartTicking();
511 WaitableMessageLoopEvent event;
512 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)))
513 .WillOnce(RunClosure(event.GetClosure()));
514 AdvanceTimeInMs(10);
515 event.RunAndWait();
517 Destroy();
520 // Verify that a late decoder response doesn't break invariants in the renderer.
521 TEST_P(VideoRendererImplTest, DestroyDuringOutstandingRead) {
522 Initialize();
523 QueueFrames("0 10 20 30");
524 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
525 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
526 StartPlayingFrom(0);
528 // Check that there is an outstanding Read() request.
529 EXPECT_TRUE(IsReadPending());
531 Destroy();
534 TEST_P(VideoRendererImplTest, VideoDecoder_InitFailure) {
535 InitializeRenderer(false, false);
536 Destroy();
539 TEST_P(VideoRendererImplTest, Underflow) {
540 Initialize();
541 QueueFrames("0 30 60 90");
544 WaitableMessageLoopEvent event;
545 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
546 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
547 .WillOnce(RunClosure(event.GetClosure()));
548 StartPlayingFrom(0);
549 event.RunAndWait();
550 Mock::VerifyAndClearExpectations(&mock_cb_);
553 renderer_->OnTimeStateChanged(true);
555 // Advance time slightly, but enough to exceed the duration of the last frame.
556 // Frames should be dropped and we should NOT signal having nothing.
558 SCOPED_TRACE("Waiting for frame drops");
559 WaitableMessageLoopEvent event;
561 // Note: Starting the TimeSource will cause the old VideoRendererImpl to
562 // start rendering frames on its own thread, so the first frame may be
563 // received.
564 time_source_.StartTicking();
565 if (GetParam())
566 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
567 else
568 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(AnyNumber());
570 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
571 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
572 .WillOnce(RunClosure(event.GetClosure()));
573 AdvanceTimeInMs(91);
575 event.RunAndWait();
576 Mock::VerifyAndClearExpectations(&mock_cb_);
579 // Advance time more. Now we should signal having nothing. And put
580 // the last frame up for display.
582 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
583 WaitableMessageLoopEvent event;
584 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
585 .WillOnce(RunClosure(event.GetClosure()));
586 AdvanceTimeInMs(30);
587 // The old rendering path needs wall clock time to increase too.
588 if (!GetParam())
589 AdvanceWallclockTimeInMs(30);
591 event.RunAndWait();
592 Mock::VerifyAndClearExpectations(&mock_cb_);
595 // Receiving end of stream should signal having enough.
597 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
598 WaitableMessageLoopEvent event;
599 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
600 .WillOnce(RunClosure(event.GetClosure()));
601 SatisfyPendingReadWithEndOfStream();
602 event.RunAndWait();
605 WaitForEnded();
606 Destroy();
609 // Verifies that the sink is stopped after rendering the first frame if
610 // playback hasn't started.
611 TEST_P(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
612 // This test is only for the new rendering path.
613 if (!GetParam())
614 return;
616 InitializeWithLowDelay(true);
617 QueueFrames("0");
619 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
620 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
623 SCOPED_TRACE("Waiting for sink to stop.");
624 WaitableMessageLoopEvent event;
626 null_video_sink_->set_background_render(true);
627 null_video_sink_->set_stop_cb(event.GetClosure());
628 StartPlayingFrom(0);
630 EXPECT_TRUE(IsReadPending());
631 SatisfyPendingReadWithEndOfStream();
633 event.RunAndWait();
636 EXPECT_FALSE(has_ended());
637 Destroy();
640 // Verifies that the sink is stopped after rendering the first frame if
641 // playback ha started.
642 TEST_P(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) {
643 // This test is only for the new rendering path.
644 if (!GetParam())
645 return;
647 InitializeWithLowDelay(true);
648 QueueFrames("0");
650 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
651 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
654 SCOPED_TRACE("Waiting for sink to stop.");
655 WaitableMessageLoopEvent event;
657 null_video_sink_->set_stop_cb(event.GetClosure());
658 StartPlayingFrom(0);
659 renderer_->OnTimeStateChanged(true);
661 EXPECT_TRUE(IsReadPending());
662 SatisfyPendingReadWithEndOfStream();
663 WaitForEnded();
665 renderer_->OnTimeStateChanged(false);
666 event.RunAndWait();
669 Destroy();
672 // Tests the case where the video started and received a single Render() call,
673 // then the video was put into the background.
674 TEST_P(VideoRendererImplTest, RenderingStartedThenStopped) {
675 // This test is only for the new rendering path.
676 if (!GetParam())
677 return;
679 Initialize();
680 QueueFrames("0 30 60 90");
682 // Start the sink and wait for the first callback. Set statistics to a non
683 // zero value, once we have some decoded frames they should be overwritten.
684 last_pipeline_statistics_.video_frames_dropped = 1;
686 WaitableMessageLoopEvent event;
687 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
688 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)))
689 .WillOnce(RunClosure(event.GetClosure()));
690 StartPlayingFrom(0);
691 event.RunAndWait();
692 Mock::VerifyAndClearExpectations(&mock_cb_);
693 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
696 renderer_->OnTimeStateChanged(true);
697 time_source_.StartTicking();
699 // Suspend all future callbacks and synthetically advance the media time,
700 // because this is a background render, we won't underflow by waiting until
701 // a pending read is ready.
702 null_video_sink_->set_background_render(true);
703 AdvanceTimeInMs(91);
704 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)));
705 WaitForPendingRead();
706 SatisfyPendingReadWithEndOfStream();
708 // If this wasn't background rendering mode, this would result in two frames
709 // being dropped, but since we set background render to true, none should be
710 // reported
711 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
712 EXPECT_EQ(4u, last_pipeline_statistics_.video_frames_decoded);
714 AdvanceTimeInMs(30);
715 WaitForEnded();
716 Destroy();
719 INSTANTIATE_TEST_CASE_P(OldVideoRenderer,
720 VideoRendererImplTest,
721 testing::Values(false));
722 INSTANTIATE_TEST_CASE_P(NewVideoRenderer,
723 VideoRendererImplTest,
724 testing::Values(true));
726 } // namespace media