Roll WebRTC 9933:9992, Libjingle 9934:9991
[chromium-blink-merge.git] / media / renderers / video_renderer_impl_unittest.cc
blob558534e2f22d61bcfa493c381e71ef34cdbc27ce
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
50 : public testing::TestWithParam<bool /* new_video_renderer */> {
51 public:
52 VideoRendererImplTest()
53 : tick_clock_(new base::SimpleTestTickClock()),
54 decoder_(new MockVideoDecoder()),
55 demuxer_stream_(DemuxerStream::VIDEO) {
56 ScopedVector<VideoDecoder> decoders;
57 decoders.push_back(decoder_);
59 null_video_sink_.reset(new NullVideoSink(
60 false, base::TimeDelta::FromSecondsD(1.0 / 60),
61 base::Bind(&MockCB::FrameReceived, base::Unretained(&mock_cb_)),
62 message_loop_.task_runner()));
64 renderer_.reset(new VideoRendererImpl(
65 message_loop_.task_runner(), message_loop_.task_runner().get(),
66 null_video_sink_.get(), decoders.Pass(), true,
67 nullptr, // gpu_factories
68 new MediaLog()));
69 if (!GetParam())
70 renderer_->disable_new_video_renderer_for_testing();
71 renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
72 null_video_sink_->set_tick_clock_for_testing(tick_clock_);
73 time_source_.set_tick_clock_for_testing(tick_clock_);
75 // Start wallclock time at a non-zero value.
76 AdvanceWallclockTimeInMs(12345);
78 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
80 // We expect these to be called but we don't care how/when.
81 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
82 RunCallback<0>(DemuxerStream::kOk,
83 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
86 virtual ~VideoRendererImplTest() {}
88 void Initialize() {
89 InitializeWithLowDelay(false);
92 void InitializeWithLowDelay(bool low_delay) {
93 // Monitor decodes from the decoder.
94 EXPECT_CALL(*decoder_, Decode(_, _))
95 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::DecodeRequested));
97 EXPECT_CALL(*decoder_, Reset(_))
98 .WillRepeatedly(Invoke(this, &VideoRendererImplTest::FlushRequested));
100 // Initialize, we shouldn't have any reads.
101 InitializeRenderer(low_delay, true);
104 void InitializeRenderer(bool low_delay, bool expect_to_success) {
105 SCOPED_TRACE(
106 base::StringPrintf("InitializeRenderer(%d)", expect_to_success));
107 WaitableMessageLoopEvent event;
108 CallInitialize(event.GetPipelineStatusCB(), low_delay, expect_to_success);
109 event.RunAndWaitForStatus(expect_to_success ? PIPELINE_OK
110 : DECODER_ERROR_NOT_SUPPORTED);
113 void CallInitialize(const PipelineStatusCB& status_cb,
114 bool low_delay,
115 bool expect_to_success) {
116 if (low_delay)
117 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE);
118 EXPECT_CALL(*decoder_, Initialize(_, _, _, _))
119 .WillOnce(
120 DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(expect_to_success)));
121 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
122 renderer_->Initialize(
123 &demuxer_stream_, status_cb, media::SetDecryptorReadyCB(),
124 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate,
125 base::Unretained(this)),
126 base::Bind(&StrictMock<MockCB>::BufferingStateChange,
127 base::Unretained(&mock_cb_)),
128 ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(),
129 base::Bind(&WallClockTimeSource::GetWallClockTimes,
130 base::Unretained(&time_source_)),
131 base::Bind(&VideoRendererImplTest::OnWaitingForDecryptionKey,
132 base::Unretained(this)));
135 void StartPlayingFrom(int milliseconds) {
136 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds));
137 const base::TimeDelta media_time =
138 base::TimeDelta::FromMilliseconds(milliseconds);
139 time_source_.SetMediaTime(media_time);
140 renderer_->StartPlayingFrom(media_time);
141 message_loop_.RunUntilIdle();
144 void Flush() {
145 SCOPED_TRACE("Flush()");
146 WaitableMessageLoopEvent event;
147 renderer_->Flush(event.GetClosure());
148 event.RunAndWait();
151 void Destroy() {
152 SCOPED_TRACE("Destroy()");
153 renderer_.reset();
154 message_loop_.RunUntilIdle();
157 // Parses a string representation of video frames and generates corresponding
158 // VideoFrame objects in |decode_results_|.
160 // Syntax:
161 // nn - Queue a decoder buffer with timestamp nn * 1000us
162 // abort - Queue an aborted read
163 // error - Queue a decoder error
165 // Examples:
166 // A clip that is four frames long: "0 10 20 30"
167 // A clip that has a decode error: "60 70 error"
168 void QueueFrames(const std::string& str) {
169 for (const std::string& token :
170 base::SplitString(str, " ", base::TRIM_WHITESPACE,
171 base::SPLIT_WANT_ALL)) {
172 if (token == "abort") {
173 scoped_refptr<VideoFrame> null_frame;
174 decode_results_.push_back(
175 std::make_pair(VideoDecoder::kAborted, null_frame));
176 continue;
179 if (token == "error") {
180 scoped_refptr<VideoFrame> null_frame;
181 decode_results_.push_back(
182 std::make_pair(VideoDecoder::kDecodeError, null_frame));
183 continue;
186 int timestamp_in_ms = 0;
187 if (base::StringToInt(token, &timestamp_in_ms)) {
188 gfx::Size natural_size = TestVideoConfig::NormalCodedSize();
189 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
190 PIXEL_FORMAT_YV12, natural_size, gfx::Rect(natural_size),
191 natural_size, base::TimeDelta::FromMilliseconds(timestamp_in_ms));
192 decode_results_.push_back(std::make_pair(VideoDecoder::kOk, frame));
193 continue;
196 CHECK(false) << "Unrecognized decoder buffer token: " << token;
200 bool IsReadPending() {
201 return !decode_cb_.is_null();
204 void WaitForError(PipelineStatus expected) {
205 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected));
206 error_event_.RunAndWaitForStatus(expected);
209 void WaitForEnded() {
210 SCOPED_TRACE("WaitForEnded()");
211 ended_event_.RunAndWait();
214 void WaitForPendingRead() {
215 SCOPED_TRACE("WaitForPendingRead()");
216 if (!decode_cb_.is_null())
217 return;
219 DCHECK(wait_for_pending_decode_cb_.is_null());
221 WaitableMessageLoopEvent event;
222 wait_for_pending_decode_cb_ = event.GetClosure();
223 event.RunAndWait();
225 DCHECK(!decode_cb_.is_null());
226 DCHECK(wait_for_pending_decode_cb_.is_null());
229 void SatisfyPendingRead() {
230 CHECK(!decode_cb_.is_null());
231 CHECK(!decode_results_.empty());
233 // Post tasks for OutputCB and DecodeCB.
234 scoped_refptr<VideoFrame> frame = decode_results_.front().second;
235 if (frame.get())
236 message_loop_.PostTask(FROM_HERE, base::Bind(output_cb_, frame));
237 message_loop_.PostTask(
238 FROM_HERE, base::Bind(base::ResetAndReturn(&decode_cb_),
239 decode_results_.front().first));
240 decode_results_.pop_front();
243 void SatisfyPendingReadWithEndOfStream() {
244 DCHECK(!decode_cb_.is_null());
246 // Return EOS buffer to trigger EOS frame.
247 EXPECT_CALL(demuxer_stream_, Read(_))
248 .WillOnce(RunCallback<0>(DemuxerStream::kOk,
249 DecoderBuffer::CreateEOSBuffer()));
251 // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read().
252 message_loop_.PostTask(
253 FROM_HERE,
254 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
256 WaitForPendingRead();
258 message_loop_.PostTask(
259 FROM_HERE,
260 base::Bind(base::ResetAndReturn(&decode_cb_), VideoDecoder::kOk));
263 void AdvanceWallclockTimeInMs(int time_ms) {
264 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
265 base::AutoLock l(lock_);
266 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(time_ms));
269 void AdvanceTimeInMs(int time_ms) {
270 DCHECK_EQ(&message_loop_, base::MessageLoop::current());
271 base::AutoLock l(lock_);
272 time_ += base::TimeDelta::FromMilliseconds(time_ms);
273 time_source_.StopTicking();
274 time_source_.SetMediaTime(time_);
275 time_source_.StartTicking();
278 bool has_ended() const {
279 return ended_event_.is_signaled();
282 protected:
283 // Fixture members.
284 scoped_ptr<VideoRendererImpl> renderer_;
285 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
286 MockVideoDecoder* decoder_; // Owned by |renderer_|.
287 NiceMock<MockDemuxerStream> demuxer_stream_;
289 // Use StrictMock<T> to catch missing/extra callbacks.
290 class MockCB {
291 public:
292 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&));
293 MOCK_METHOD1(BufferingStateChange, void(BufferingState));
295 StrictMock<MockCB> mock_cb_;
297 // Must be destroyed before |renderer_| since they share |tick_clock_|.
298 scoped_ptr<NullVideoSink> null_video_sink_;
300 PipelineStatistics last_pipeline_statistics_;
302 WallClockTimeSource time_source_;
304 base::MessageLoop message_loop_;
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 // Used to protect |time_|.
341 base::Lock lock_;
342 base::TimeDelta time_;
344 // Used for satisfying reads.
345 VideoDecoder::OutputCB output_cb_;
346 VideoDecoder::DecodeCB decode_cb_;
347 base::TimeDelta next_frame_timestamp_;
349 WaitableMessageLoopEvent error_event_;
350 WaitableMessageLoopEvent ended_event_;
352 // Run during DecodeRequested() to unblock WaitForPendingRead().
353 base::Closure wait_for_pending_decode_cb_;
355 std::deque<std::pair<
356 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_;
358 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
361 TEST_P(VideoRendererImplTest, DoNothing) {
362 // Test that creation and deletion doesn't depend on calls to Initialize()
363 // and/or Destroy().
366 TEST_P(VideoRendererImplTest, DestroyWithoutInitialize) {
367 Destroy();
370 TEST_P(VideoRendererImplTest, Initialize) {
371 Initialize();
372 Destroy();
375 TEST_P(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
376 Initialize();
377 QueueFrames("0 10 20 30");
378 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
379 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
380 StartPlayingFrom(0);
381 Destroy();
384 TEST_P(VideoRendererImplTest, InitializeAndEndOfStream) {
385 Initialize();
386 StartPlayingFrom(0);
387 WaitForPendingRead();
389 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
390 WaitableMessageLoopEvent event;
391 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
392 .WillOnce(RunClosure(event.GetClosure()));
393 SatisfyPendingReadWithEndOfStream();
394 event.RunAndWait();
396 // Firing a time state changed to true should be ignored...
397 renderer_->OnTimeStateChanged(true);
398 EXPECT_FALSE(null_video_sink_->is_started());
399 Destroy();
402 TEST_P(VideoRendererImplTest, DestroyWhileInitializing) {
403 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK);
404 Destroy();
407 TEST_P(VideoRendererImplTest, DestroyWhileFlushing) {
408 Initialize();
409 QueueFrames("0 10 20 30");
410 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
411 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
412 StartPlayingFrom(0);
413 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING));
414 renderer_->Flush(NewExpectedClosure());
415 Destroy();
418 TEST_P(VideoRendererImplTest, Play) {
419 Initialize();
420 QueueFrames("0 10 20 30");
421 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
422 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
423 StartPlayingFrom(0);
424 Destroy();
427 TEST_P(VideoRendererImplTest, FlushWithNothingBuffered) {
428 Initialize();
429 StartPlayingFrom(0);
431 // We shouldn't expect a buffering state change since we never reached
432 // BUFFERING_HAVE_ENOUGH.
433 Flush();
434 Destroy();
437 TEST_P(VideoRendererImplTest, DecodeError_Playing) {
438 Initialize();
439 QueueFrames("0 10 20 30");
440 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
441 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
442 StartPlayingFrom(0);
443 renderer_->OnTimeStateChanged(true);
444 time_source_.StartTicking();
445 AdvanceTimeInMs(10);
447 QueueFrames("error");
448 SatisfyPendingRead();
449 WaitForError(PIPELINE_ERROR_DECODE);
450 Destroy();
453 TEST_P(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
454 Initialize();
455 QueueFrames("error");
456 StartPlayingFrom(0);
457 Destroy();
460 TEST_P(VideoRendererImplTest, StartPlayingFrom_Exact) {
461 Initialize();
462 QueueFrames("50 60 70 80 90");
464 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
465 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
466 StartPlayingFrom(60);
467 Destroy();
470 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
471 Initialize();
472 QueueFrames("50 60 70 80 90");
474 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50)));
475 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
476 StartPlayingFrom(59);
477 Destroy();
480 TEST_P(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
481 Initialize();
482 QueueFrames("50 60 70 80 90");
484 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60)));
485 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
486 StartPlayingFrom(61);
487 Destroy();
490 TEST_P(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
491 // In low-delay mode only one frame is required to finish preroll. But frames
492 // prior to the start time will not be used.
493 InitializeWithLowDelay(true);
494 QueueFrames("0 10");
496 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)));
497 // Expect some amount of have enough/nothing due to only requiring one frame.
498 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
499 .Times(AnyNumber());
500 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
501 .Times(AnyNumber());
502 StartPlayingFrom(10);
504 QueueFrames("20");
505 SatisfyPendingRead();
507 renderer_->OnTimeStateChanged(true);
508 time_source_.StartTicking();
510 WaitableMessageLoopEvent event;
511 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20)))
512 .WillOnce(RunClosure(event.GetClosure()));
513 AdvanceTimeInMs(20);
514 event.RunAndWait();
516 Destroy();
519 // Verify that a late decoder response doesn't break invariants in the renderer.
520 TEST_P(VideoRendererImplTest, DestroyDuringOutstandingRead) {
521 Initialize();
522 QueueFrames("0 10 20 30");
523 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
524 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
525 StartPlayingFrom(0);
527 // Check that there is an outstanding Read() request.
528 EXPECT_TRUE(IsReadPending());
530 Destroy();
533 TEST_P(VideoRendererImplTest, VideoDecoder_InitFailure) {
534 InitializeRenderer(false, false);
535 Destroy();
538 TEST_P(VideoRendererImplTest, Underflow) {
539 Initialize();
540 QueueFrames("0 30 60 90");
543 WaitableMessageLoopEvent event;
544 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
545 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
546 .WillOnce(RunClosure(event.GetClosure()));
547 StartPlayingFrom(0);
548 event.RunAndWait();
549 Mock::VerifyAndClearExpectations(&mock_cb_);
552 renderer_->OnTimeStateChanged(true);
554 // Advance time slightly, but enough to exceed the duration of the last frame.
555 // Frames should be dropped and we should NOT signal having nothing.
557 SCOPED_TRACE("Waiting for frame drops");
558 WaitableMessageLoopEvent event;
560 // Note: Starting the TimeSource will cause the old VideoRendererImpl to
561 // start rendering frames on its own thread, so the first frame may be
562 // received.
563 time_source_.StartTicking();
564 if (GetParam())
565 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
566 else
567 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(AnyNumber());
569 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
570 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
571 .WillOnce(RunClosure(event.GetClosure()));
572 AdvanceTimeInMs(91);
574 event.RunAndWait();
575 Mock::VerifyAndClearExpectations(&mock_cb_);
578 // Advance time more. Now we should signal having nothing. And put
579 // the last frame up for display.
581 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
582 WaitableMessageLoopEvent event;
583 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
584 .WillOnce(RunClosure(event.GetClosure()));
585 AdvanceTimeInMs(30);
586 // The old rendering path needs wall clock time to increase too.
587 if (!GetParam())
588 AdvanceWallclockTimeInMs(30);
590 event.RunAndWait();
591 Mock::VerifyAndClearExpectations(&mock_cb_);
594 // Receiving end of stream should signal having enough.
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();
604 WaitForEnded();
605 Destroy();
608 // Verifies that the sink is stopped after rendering the first frame if
609 // playback hasn't started.
610 TEST_P(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
611 // This test is only for the new rendering path.
612 if (!GetParam())
613 return;
615 InitializeWithLowDelay(true);
616 QueueFrames("0");
618 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
619 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
622 SCOPED_TRACE("Waiting for sink to stop.");
623 WaitableMessageLoopEvent event;
625 null_video_sink_->set_background_render(true);
626 null_video_sink_->set_stop_cb(event.GetClosure());
627 StartPlayingFrom(0);
629 EXPECT_TRUE(IsReadPending());
630 SatisfyPendingReadWithEndOfStream();
632 event.RunAndWait();
635 EXPECT_FALSE(has_ended());
636 Destroy();
639 // Verifies that the sink is stopped after rendering the first frame if
640 // playback ha started.
641 TEST_P(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) {
642 // This test is only for the new rendering path.
643 if (!GetParam())
644 return;
646 InitializeWithLowDelay(true);
647 QueueFrames("0");
649 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
650 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
653 SCOPED_TRACE("Waiting for sink to stop.");
654 WaitableMessageLoopEvent event;
656 null_video_sink_->set_stop_cb(event.GetClosure());
657 StartPlayingFrom(0);
658 renderer_->OnTimeStateChanged(true);
660 EXPECT_TRUE(IsReadPending());
661 SatisfyPendingReadWithEndOfStream();
662 WaitForEnded();
664 renderer_->OnTimeStateChanged(false);
665 event.RunAndWait();
668 Destroy();
671 // Tests the case where the video started and received a single Render() call,
672 // then the video was put into the background.
673 TEST_P(VideoRendererImplTest, RenderingStartedThenStopped) {
674 // This test is only for the new rendering path.
675 if (!GetParam())
676 return;
678 Initialize();
679 QueueFrames("0 30 60 90");
681 // Start the sink and wait for the first callback. Set statistics to a non
682 // zero value, once we have some decoded frames they should be overwritten.
683 last_pipeline_statistics_.video_frames_dropped = 1;
685 WaitableMessageLoopEvent event;
686 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
687 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)))
688 .WillOnce(RunClosure(event.GetClosure()));
689 StartPlayingFrom(0);
690 event.RunAndWait();
691 Mock::VerifyAndClearExpectations(&mock_cb_);
692 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
695 renderer_->OnTimeStateChanged(true);
696 time_source_.StartTicking();
698 // Suspend all future callbacks and synthetically advance the media time,
699 // because this is a background render, we won't underflow by waiting until
700 // a pending read is ready.
701 null_video_sink_->set_background_render(true);
702 AdvanceTimeInMs(91);
703 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)));
704 WaitForPendingRead();
705 SatisfyPendingReadWithEndOfStream();
707 // If this wasn't background rendering mode, this would result in two frames
708 // being dropped, but since we set background render to true, none should be
709 // reported
710 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped);
711 EXPECT_EQ(4u, last_pipeline_statistics_.video_frames_decoded);
713 AdvanceTimeInMs(30);
714 WaitForEnded();
715 Destroy();
718 TEST_P(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) {
719 // This test is only for the new rendering path.
720 if (!GetParam())
721 return;
723 Initialize();
724 QueueFrames("0 30 60 90");
726 WaitableMessageLoopEvent event;
727 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
728 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
729 .WillOnce(RunClosure(event.GetClosure()));
730 StartPlayingFrom(0);
731 event.RunAndWait();
733 // Cycle ticking so that we get a non-null reference time.
734 time_source_.StartTicking();
735 time_source_.StopTicking();
737 // Flush and simulate a seek past EOS, where some error prevents the decoder
738 // from returning any frames.
739 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING));
740 Flush();
742 StartPlayingFrom(200);
743 WaitForPendingRead();
744 SatisfyPendingReadWithEndOfStream();
745 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
746 WaitForEnded();
747 Destroy();
750 INSTANTIATE_TEST_CASE_P(OldVideoRenderer,
751 VideoRendererImplTest,
752 testing::Values(false));
753 INSTANTIATE_TEST_CASE_P(NewVideoRenderer,
754 VideoRendererImplTest,
755 testing::Values(true));
757 namespace {
758 class MockGpuMemoryBufferVideoFramePool : public GpuMemoryBufferVideoFramePool {
759 public:
760 MockGpuMemoryBufferVideoFramePool(std::vector<base::Closure>* frame_ready_cbs)
761 : frame_ready_cbs_(frame_ready_cbs) {}
762 void MaybeCreateHardwareFrame(const scoped_refptr<VideoFrame>& video_frame,
763 const FrameReadyCB& frame_ready_cb) override {
764 frame_ready_cbs_->push_back(base::Bind(frame_ready_cb, video_frame));
767 private:
768 std::vector<base::Closure>* frame_ready_cbs_;
772 class VideoRendererImplAsyncAddFrameReadyTest : public VideoRendererImplTest {
773 public:
774 VideoRendererImplAsyncAddFrameReadyTest() {
775 scoped_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool(
776 new MockGpuMemoryBufferVideoFramePool(&frame_ready_cbs_));
777 renderer_->SetGpuMemoryBufferVideoForTesting(gpu_memory_buffer_pool.Pass());
780 protected:
781 std::vector<base::Closure> frame_ready_cbs_;
784 TEST_P(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) {
785 Initialize();
786 QueueFrames("0 10 20 30");
787 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
788 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
789 StartPlayingFrom(0);
790 ASSERT_EQ(1u, frame_ready_cbs_.size());
792 uint32_t frame_ready_index = 0;
793 while (frame_ready_index < frame_ready_cbs_.size()) {
794 frame_ready_cbs_[frame_ready_index++].Run();
795 message_loop_.RunUntilIdle();
797 Destroy();
800 TEST_P(VideoRendererImplAsyncAddFrameReadyTest, SequenceTokenDiscardOneFrame) {
801 Initialize();
802 QueueFrames("0 10 20 30");
803 StartPlayingFrom(0);
804 Flush();
805 ASSERT_EQ(1u, frame_ready_cbs_.size());
806 // This frame will be discarded.
807 frame_ready_cbs_.front().Run();
808 Destroy();
811 INSTANTIATE_TEST_CASE_P(NewVideoRenderer,
812 VideoRendererImplAsyncAddFrameReadyTest,
813 testing::Values(true));
815 } // namespace media