1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "base/containers/circular_deque.h"
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/synchronization/lock.h"
21 #include "base/task/single_thread_task_runner.h"
22 #include "base/test/gmock_callback_support.h"
23 #include "base/test/simple_test_tick_clock.h"
24 #include "base/test/task_environment.h"
25 #include "base/time/time.h"
26 #include "media/base/data_buffer.h"
27 #include "media/base/limits.h"
28 #include "media/base/media_switches.h"
29 #include "media/base/media_util.h"
30 #include "media/base/mock_filters.h"
31 #include "media/base/null_video_sink.h"
32 #include "media/base/test_helpers.h"
33 #include "media/base/video_frame.h"
34 #include "media/base/wall_clock_time_source.h"
35 #include "media/renderers/video_renderer_impl.h"
36 #include "media/video/mock_gpu_memory_buffer_video_frame_pool.h"
37 #include "testing/gtest/include/gtest/gtest.h"
39 using ::base::test::RunClosure;
40 using ::base::test::RunOnceCallback;
41 using ::base::test::RunOnceClosure;
43 using ::testing::AnyNumber;
44 using ::testing::Combine;
45 using ::testing::DoAll;
46 using ::testing::Invoke;
47 using ::testing::Mock;
48 using ::testing::NiceMock;
49 using ::testing::Return;
50 using ::testing::SaveArg;
51 using ::testing::StrictMock;
52 using ::testing::Values;
56 MATCHER_P(HasTimestampMatcher, ms, "") {
57 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds();
58 return arg->timestamp().InMilliseconds() == ms;
61 class VideoRendererImplTest : public testing::Test {
63 std::vector<std::unique_ptr<VideoDecoder>> CreateVideoDecodersForTest() {
64 decoder_ = new NiceMock<MockVideoDecoder>();
65 std::vector<std::unique_ptr<VideoDecoder>> decoders;
66 decoders.push_back(base::WrapUnique(decoder_.get()));
67 ON_CALL(*decoder_, Initialize_(_, _, _, _, _, _))
69 DoAll(SaveArg<4>(&output_cb_),
70 RunOnceCallback<3>(expect_init_success_
71 ? DecoderStatus::Codes::kOk
72 : DecoderStatus::Codes::kFailed)));
73 // Monitor decodes from the decoder.
74 ON_CALL(*decoder_, Decode_(_, _))
75 .WillByDefault(Invoke(this, &VideoRendererImplTest::DecodeRequested));
76 ON_CALL(*decoder_, Reset_(_))
77 .WillByDefault(Invoke(this, &VideoRendererImplTest::FlushRequested));
78 ON_CALL(*decoder_, GetMaxDecodeRequests()).WillByDefault(Return(1));
82 VideoRendererImplTest()
83 : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
85 demuxer_stream_(DemuxerStream::VIDEO),
86 simulate_decode_delay_(false),
87 expect_init_success_(true),
88 time_source_(&tick_clock_) {
89 null_video_sink_ = std::make_unique<NullVideoSink>(
90 false, base::Seconds(1.0 / 60),
91 base::BindRepeating(&MockCB::FrameReceived,
92 base::Unretained(&mock_cb_)),
93 base::SingleThreadTaskRunner::GetCurrentDefault());
95 renderer_ = std::make_unique<VideoRendererImpl>(
96 base::SingleThreadTaskRunner::GetCurrentDefault(),
97 null_video_sink_.get(),
98 base::BindRepeating(&VideoRendererImplTest::CreateVideoDecodersForTest,
99 base::Unretained(this)),
100 true, &media_log_, nullptr, 0);
101 renderer_->SetTickClockForTesting(&tick_clock_);
102 null_video_sink_->set_tick_clock_for_testing(&tick_clock_);
104 // Start wallclock time at a non-zero value.
105 AdvanceWallclockTimeInMs(12345);
107 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal());
109 // We expect these to be called but we don't care how/when. Tests can
110 // customize the provided buffer returned via OnDemuxerRead().
111 ON_CALL(demuxer_stream_, OnRead(_))
112 .WillByDefault(Invoke(this, &VideoRendererImplTest::OnDemuxerRead));
115 VideoRendererImplTest(const VideoRendererImplTest&) = delete;
116 VideoRendererImplTest& operator=(const VideoRendererImplTest&) = delete;
118 ~VideoRendererImplTest() override = default;
121 InitializeWithLowDelay(false);
124 void InitializeWithLowDelay(bool low_delay) {
125 // Initialize, we shouldn't have any reads.
126 InitializeRenderer(&demuxer_stream_, low_delay, true);
129 void InitializeRenderer(MockDemuxerStream* demuxer_stream,
131 bool expect_success) {
132 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expect_success));
133 expect_init_success_ = expect_success;
134 WaitableMessageLoopEvent event;
135 CallInitialize(demuxer_stream, event.GetPipelineStatusCB(), low_delay,
137 event.RunAndWaitForStatus(expect_success ? PIPELINE_OK
138 : DECODER_ERROR_NOT_SUPPORTED);
141 void CallInitialize(MockDemuxerStream* demuxer_stream,
142 PipelineStatusCallback status_cb,
144 bool expect_success) {
146 demuxer_stream->set_liveness(StreamLiveness::kLive);
147 EXPECT_CALL(mock_cb_, OnWaiting(_)).Times(0);
148 EXPECT_CALL(mock_cb_, OnAudioConfigChange(_)).Times(0);
149 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
150 renderer_->Initialize(
151 demuxer_stream, nullptr, &mock_cb_,
152 base::BindRepeating(&WallClockTimeSource::GetWallClockTimes,
153 base::Unretained(&time_source_)),
154 std::move(status_cb));
157 void StartPlayingFrom(int milliseconds) {
158 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds));
159 const base::TimeDelta media_time = base::Milliseconds(milliseconds);
160 time_source_.SetMediaTime(media_time);
161 renderer_->StartPlayingFrom(media_time);
162 base::RunLoop().RunUntilIdle();
166 SCOPED_TRACE("Flush()");
167 WaitableMessageLoopEvent event;
168 renderer_->Flush(event.GetClosure());
173 SCOPED_TRACE("Destroy()");
175 base::RunLoop().RunUntilIdle();
178 void OnDemuxerRead(DemuxerStream::ReadCB& read_cb) {
179 if (simulate_demuxer_stall_after_n_reads_ >= 0) {
180 if (simulate_demuxer_stall_after_n_reads_-- == 0) {
181 stalled_demixer_read_cb_ = std::move(read_cb);
186 scoped_refptr<DecoderBuffer> decoder_buffer(new DecoderBuffer(0));
188 // Set |decoder_buffer| timestamp such that it won't match any of the
189 // times provided to QueueFrames(). Otherwise the default timestamp of 0 may
190 // match some frames and not others, which causes non-uniform handling in
191 // DecoderStreamTraits.
192 decoder_buffer->set_timestamp(kNoTimestamp);
194 // Test hook for to specify a custom buffer duration.
195 decoder_buffer->set_duration(buffer_duration_);
197 std::move(read_cb).Run(DemuxerStream::kOk, {std::move(decoder_buffer)});
200 bool IsDemuxerStalled() { return !!stalled_demixer_read_cb_; }
202 void UnstallDemuxer() {
203 EXPECT_TRUE(IsDemuxerStalled());
204 OnDemuxerRead(stalled_demixer_read_cb_);
207 // Parses a string representation of video frames and generates corresponding
208 // VideoFrame objects in |decode_results_|.
211 // nn - Queue a decoder buffer with timestamp nn * 1000us
212 // nndmm - Queue a decoder buffer with timestamp nn * 1000us
213 // and mm * 1000us duration
214 // abort - Queue an aborted read
215 // error - Queue a decoder error
218 // A clip that is four frames long: "0 10 20 30"
219 // A clip that has a decode error: "60 70 error"
220 void QueueFrames(const std::string& str) {
221 for (base::StringPiece token : base::SplitString(
222 str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
223 if (token == "abort") {
224 scoped_refptr<VideoFrame> null_frame;
225 QueueFrame(DecoderStatus::Codes::kAborted, null_frame);
229 if (token == "error") {
230 scoped_refptr<VideoFrame> null_frame;
231 QueueFrame(DecoderStatus::Codes::kFailed, null_frame);
235 auto ts_tokens = base::SplitStringPiece(token, "d", base::TRIM_WHITESPACE,
236 base::SPLIT_WANT_ALL);
237 if (ts_tokens.size() > 1) {
238 token = ts_tokens[0];
241 int timestamp_in_ms = 0;
242 if (base::StringToInt(token, ×tamp_in_ms)) {
243 gfx::Size natural_size = TestVideoConfig::NormalCodedSize();
244 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
245 PIXEL_FORMAT_I420, natural_size, gfx::Rect(natural_size),
246 natural_size, base::Milliseconds(timestamp_in_ms));
248 int duration_in_ms = 0;
249 if (ts_tokens.size() > 1 &&
250 base::StringToInt(ts_tokens[1], &duration_in_ms)) {
251 frame->metadata().frame_duration = base::Milliseconds(duration_in_ms);
254 QueueFrame(DecoderStatus::Codes::kOk, frame);
258 CHECK(false) << "Unrecognized decoder buffer token: " << token;
262 // Queues video frames to be served by the decoder during rendering.
263 void QueueFrame(DecoderStatus status, scoped_refptr<VideoFrame> frame) {
264 decode_results_.push_back(std::make_pair(status, frame));
267 bool IsDecodePending() { return !!decode_cb_; }
269 void WaitForError(PipelineStatus expected) {
270 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected.code()));
272 WaitableMessageLoopEvent event;
273 PipelineStatusCallback error_cb = event.GetPipelineStatusCB();
274 EXPECT_CALL(mock_cb_, OnError(_))
275 .WillOnce(Invoke([cb = &error_cb](PipelineStatus status) {
276 std::move(*cb).Run(status);
278 event.RunAndWaitForStatus(expected);
281 void WaitForEnded() {
282 SCOPED_TRACE("WaitForEnded()");
284 WaitableMessageLoopEvent event;
285 EXPECT_CALL(mock_cb_, OnEnded())
286 .WillOnce(RunOnceClosure(event.GetClosure()));
290 void WaitForPendingDecode() {
291 SCOPED_TRACE("WaitForPendingDecode()");
295 DCHECK(!wait_for_pending_decode_cb_);
297 WaitableMessageLoopEvent event;
298 wait_for_pending_decode_cb_ = event.GetClosure();
302 DCHECK(!wait_for_pending_decode_cb_);
305 void SatisfyPendingDecode() {
307 CHECK(!decode_results_.empty());
309 // Post tasks for OutputCB and DecodeCB.
310 scoped_refptr<VideoFrame> frame = decode_results_.front().second;
312 task_environment_.GetMainThreadTaskRunner()->PostTask(
313 FROM_HERE, base::BindOnce(output_cb_, frame));
314 task_environment_.GetMainThreadTaskRunner()->PostTask(
316 base::BindOnce(std::move(decode_cb_), decode_results_.front().first));
317 decode_results_.pop_front();
320 void SatisfyPendingDecodeWithEndOfStream() {
323 // Return EOS buffer to trigger EOS frame.
324 DemuxerStream::DecoderBufferVector buffers;
325 buffers.emplace_back(DecoderBuffer::CreateEOSBuffer());
326 EXPECT_CALL(demuxer_stream_, OnRead(_))
327 .WillOnce(RunOnceCallback<0>(DemuxerStream::kOk, buffers));
329 // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read().
330 task_environment_.GetMainThreadTaskRunner()->PostTask(
332 base::BindOnce(std::move(decode_cb_), DecoderStatus::Codes::kOk));
334 WaitForPendingDecode();
336 task_environment_.GetMainThreadTaskRunner()->PostTask(
338 base::BindOnce(std::move(decode_cb_), DecoderStatus::Codes::kOk));
341 bool HasQueuedFrames() const { return decode_results_.size() > 0; }
343 void AdvanceWallclockTimeInMs(int time_ms) {
345 task_environment_.GetMainThreadTaskRunner()->BelongsToCurrentThread());
346 base::AutoLock l(lock_);
347 tick_clock_.Advance(base::Milliseconds(time_ms));
350 void AdvanceTimeInMs(int time_ms) {
352 task_environment_.GetMainThreadTaskRunner()->BelongsToCurrentThread());
353 base::AutoLock l(lock_);
354 time_ += base::Milliseconds(time_ms);
355 time_source_.StopTicking();
356 time_source_.SetMediaTime(time_);
357 time_source_.StartTicking();
360 MOCK_METHOD0(OnSimulateDecodeDelay, base::TimeDelta(void));
363 base::test::TaskEnvironment task_environment_;
364 NullMediaLog media_log_;
367 std::unique_ptr<VideoRendererImpl> renderer_;
368 base::SimpleTestTickClock tick_clock_;
369 raw_ptr<NiceMock<MockVideoDecoder>, DanglingUntriaged>
370 decoder_; // Owned by |renderer_|.
371 NiceMock<MockDemuxerStream> demuxer_stream_;
372 bool simulate_decode_delay_;
374 bool expect_init_success_;
376 // Specifies how many reads should complete before demuxer stalls.
377 int simulate_demuxer_stall_after_n_reads_ = -1;
378 DemuxerStream::ReadCB stalled_demixer_read_cb_;
380 // Use StrictMock<T> to catch missing/extra callbacks.
381 class MockCB : public MockRendererClient {
383 MOCK_METHOD1(FrameReceived, void(scoped_refptr<VideoFrame>));
385 StrictMock<MockCB> mock_cb_;
387 // Must be destroyed before |renderer_| since they share |tick_clock_|.
388 std::unique_ptr<NullVideoSink> null_video_sink_;
390 WallClockTimeSource time_source_;
392 // Duration set on DecoderBuffers. See OnDemuxerRead().
393 base::TimeDelta buffer_duration_;
396 void DecodeRequested(scoped_refptr<DecoderBuffer> buffer,
397 VideoDecoder::DecodeCB& decode_cb) {
399 task_environment_.GetMainThreadTaskRunner()->BelongsToCurrentThread());
401 decode_cb_ = std::move(decode_cb);
403 // Wake up WaitForPendingDecode() if needed.
404 if (wait_for_pending_decode_cb_)
405 std::move(wait_for_pending_decode_cb_).Run();
407 if (decode_results_.empty())
410 if (simulate_decode_delay_)
411 tick_clock_.Advance(OnSimulateDecodeDelay());
413 SatisfyPendingDecode();
416 void FlushRequested(base::OnceClosure& callback) {
418 task_environment_.GetMainThreadTaskRunner()->BelongsToCurrentThread());
419 decode_results_.clear();
421 QueueFrames("abort");
422 SatisfyPendingDecode();
425 task_environment_.GetMainThreadTaskRunner()->PostTask(FROM_HERE,
426 std::move(callback));
429 // Used to protect |time_|.
431 base::TimeDelta time_;
433 // Used for satisfying reads.
434 VideoDecoder::OutputCB output_cb_;
435 VideoDecoder::DecodeCB decode_cb_;
436 base::TimeDelta next_frame_timestamp_;
438 // Run during DecodeRequested() to unblock WaitForPendingDecode().
439 base::OnceClosure wait_for_pending_decode_cb_;
441 base::circular_deque<std::pair<DecoderStatus, scoped_refptr<VideoFrame>>>
445 TEST_F(VideoRendererImplTest, DoNothing) {
446 // Test that creation and deletion doesn't depend on calls to Initialize()
450 TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) {
454 TEST_F(VideoRendererImplTest, Initialize) {
459 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
461 QueueFrames("0 10 20 30");
462 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
463 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
464 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
465 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
466 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
471 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFromWithDuration) {
473 QueueFrames("0d10 10d10 20d10 30d10 40d10");
474 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(10)));
475 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
476 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
477 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
478 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
479 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(100)));
480 StartPlayingFrom(10);
484 TEST_F(VideoRendererImplTest, InitializeAndEndOfStream) {
487 WaitForPendingDecode();
489 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
490 WaitableMessageLoopEvent event;
492 // Buffering state changes must happen before end of stream.
493 testing::InSequence in_sequence;
494 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
495 .WillOnce(RunOnceClosure(event.GetClosure()));
496 EXPECT_CALL(mock_cb_, OnEnded());
498 SatisfyPendingDecodeWithEndOfStream();
501 // Firing a time state changed to true should be ignored...
502 renderer_->OnTimeProgressing();
503 EXPECT_FALSE(null_video_sink_->is_started());
507 TEST_F(VideoRendererImplTest, StartPlayingAfterEndOfStream) {
509 QueueFrames("0d10 10d10 20d10 30d10 40d10");
510 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
511 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(40)));
512 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
513 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
514 StartPlayingFrom(40);
515 WaitForPendingDecode();
517 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
518 WaitableMessageLoopEvent event;
520 // Buffering state changes must happen before end of stream.
521 testing::InSequence in_sequence;
522 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
523 .WillOnce(RunOnceClosure(event.GetClosure()));
524 EXPECT_CALL(mock_cb_, OnEnded());
526 SatisfyPendingDecodeWithEndOfStream();
529 // Firing a time state changed to true should be ignored...
530 renderer_->OnTimeProgressing();
531 EXPECT_FALSE(null_video_sink_->is_started());
535 TEST_F(VideoRendererImplTest, InitializeAndEndOfStreamOneStaleFrame) {
537 StartPlayingFrom(10000);
539 QueueFrame(DecoderStatus::Codes::kOk, VideoFrame::CreateEOSFrame());
540 WaitForPendingDecode();
542 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
543 WaitableMessageLoopEvent event;
545 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
546 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
547 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
548 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
551 // Buffering state changes must happen before end of stream.
552 testing::InSequence in_sequence;
553 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
554 .WillOnce(RunOnceClosure(event.GetClosure()));
555 EXPECT_CALL(mock_cb_, OnEnded());
557 SatisfyPendingDecode();
560 // Firing a time state changed to true should be ignored...
561 renderer_->OnTimeProgressing();
562 EXPECT_FALSE(null_video_sink_->is_started());
566 TEST_F(VideoRendererImplTest, ReinitializeForAnotherStream) {
570 NiceMock<MockDemuxerStream> new_stream(DemuxerStream::VIDEO);
571 new_stream.set_video_decoder_config(TestVideoConfig::Normal());
572 InitializeRenderer(&new_stream, false, true);
575 TEST_F(VideoRendererImplTest, DestroyWhileInitializing) {
576 CallInitialize(&demuxer_stream_, NewExpectedStatusCB(PIPELINE_ERROR_ABORT),
581 TEST_F(VideoRendererImplTest, DestroyWhileFlushing) {
583 QueueFrames("0 10 20 30");
584 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
585 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
586 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
587 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
588 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
590 renderer_->Flush(NewExpectedClosure());
594 TEST_F(VideoRendererImplTest, Play) {
596 QueueFrames("0 10 20 30");
597 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
598 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
599 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
600 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
601 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
606 TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) {
610 // We shouldn't expect a buffering state change since we never reached
611 // BUFFERING_HAVE_ENOUGH.
616 // Verify that the flush callback is invoked outside of VideoRenderer lock, so
617 // we should be able to call other renderer methods from the Flush callback.
618 static void VideoRendererImplTest_FlushDoneCB(VideoRendererImplTest* test,
619 VideoRenderer* renderer,
620 base::OnceClosure success_cb) {
621 test->QueueFrames("0 10 20 30");
622 renderer->StartPlayingFrom(base::Seconds(0));
623 std::move(success_cb).Run();
626 TEST_F(VideoRendererImplTest, FlushCallbackNoLock) {
628 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
629 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
630 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
631 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
633 WaitableMessageLoopEvent event;
635 base::BindOnce(&VideoRendererImplTest_FlushDoneCB, base::Unretained(this),
636 base::Unretained(renderer_.get()), event.GetClosure()));
641 TEST_F(VideoRendererImplTest, DecodeError_Playing) {
643 QueueFrames("0 10 20 30");
644 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
646 // Consider the case that rendering is faster than we setup the test event.
647 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will
649 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
650 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _))
651 .Times(testing::AtMost(1));
652 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
653 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
654 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
657 renderer_->OnTimeProgressing();
658 time_source_.StartTicking();
661 QueueFrames("error");
662 SatisfyPendingDecode();
663 WaitForError(PIPELINE_ERROR_DECODE);
667 TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
669 QueueFrames("error");
670 EXPECT_CALL(mock_cb_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
671 EXPECT_CALL(mock_cb_, OnFallback(HasStatusCode(PIPELINE_ERROR_DECODE)));
676 TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) {
678 QueueFrames("50 60 70 80 90");
680 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(60)));
681 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
682 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
683 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
684 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
685 StartPlayingFrom(60);
689 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
691 QueueFrames("50 60 70 80 90");
693 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(50)));
694 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
695 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
696 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
697 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
698 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(100)));
699 StartPlayingFrom(59);
703 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
705 QueueFrames("50 60 70 80 90");
707 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(60)));
708 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
709 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
710 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
711 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
712 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(100)));
713 StartPlayingFrom(61);
717 TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
718 // In low-delay mode only one frame is required to finish preroll. But frames
719 // prior to the start time will not be used.
720 InitializeWithLowDelay(true);
723 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(10)));
724 // Expect some amount of have enough/nothing due to only requiring one frame.
725 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
727 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _))
729 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
730 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
731 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
732 StartPlayingFrom(10);
735 SatisfyPendingDecode();
737 renderer_->OnTimeProgressing();
738 time_source_.StartTicking();
740 WaitableMessageLoopEvent event;
741 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(20)))
742 .WillOnce(RunOnceClosure(event.GetClosure()));
749 // Verify that a late decoder response doesn't break invariants in the renderer.
750 TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) {
752 QueueFrames("0 10 20 30");
753 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
754 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
755 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
756 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
757 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
760 // Check that there is an outstanding Read() request.
761 EXPECT_TRUE(IsDecodePending());
766 // Verifies that the first frame is painted w/o rendering being started.
767 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) {
768 InitializeWithLowDelay(true);
771 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
772 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
773 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
774 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
775 EXPECT_CALL(mock_cb_, OnEnded()).Times(0);
778 SCOPED_TRACE("Waiting for first frame to be painted.");
779 WaitableMessageLoopEvent event;
781 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)))
782 .WillOnce(RunOnceClosure(event.GetClosure()));
785 EXPECT_TRUE(IsDecodePending());
786 SatisfyPendingDecodeWithEndOfStream();
793 // Verifies that the first frame is eventually painted even if its not the best.
794 TEST_F(VideoRendererImplTest, PaintFirstFrameOnStall) {
797 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
799 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
800 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
801 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
802 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
803 EXPECT_CALL(mock_cb_, OnEnded()).Times(0);
806 SCOPED_TRACE("Waiting for first frame to be painted.");
807 WaitableMessageLoopEvent event;
809 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)))
810 .WillOnce(RunOnceClosure(event.GetClosure()));
811 StartPlayingFrom(10);
813 EXPECT_TRUE(IsDecodePending());
821 // Verifies that the sink is stopped after rendering the first frame if
822 // playback has started.
823 TEST_F(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) {
824 InitializeWithLowDelay(true);
827 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0))).Times(1);
828 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
829 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
830 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
831 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
834 SCOPED_TRACE("Waiting for sink to stop.");
835 WaitableMessageLoopEvent event;
837 null_video_sink_->set_stop_cb(event.GetClosure());
839 renderer_->OnTimeProgressing();
841 EXPECT_TRUE(IsDecodePending());
842 SatisfyPendingDecodeWithEndOfStream();
845 renderer_->OnTimeStopped();
852 // Tests the case where the video started and received a single Render() call,
853 // then the video was put into the background.
854 TEST_F(VideoRendererImplTest, RenderingStartedThenStopped) {
856 QueueFrames("0 30 60 90");
858 // Start the sink and wait for the first callback. Set statistics to a non
859 // zero value, once we have some decoded frames they should be overwritten.
860 PipelineStatistics last_pipeline_statistics;
861 last_pipeline_statistics.video_frames_dropped = 1;
863 WaitableMessageLoopEvent event;
864 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
865 .WillOnce(RunOnceClosure(event.GetClosure()));
866 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_))
868 .WillRepeatedly(SaveArg<0>(&last_pipeline_statistics));
869 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
870 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
871 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
874 Mock::VerifyAndClearExpectations(&mock_cb_);
877 // Four calls to update statistics should have been made, each reporting a
878 // single decoded frame and one frame worth of memory usage. No dropped frames
879 // should be reported later since we're in background rendering mode. These
880 // calls must all have occurred before playback starts.
881 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped);
882 EXPECT_EQ(1u, last_pipeline_statistics.video_frames_decoded);
884 // Note: This is not the total, but just the increase in the last call since
885 // the previous call, the total should be 4 * 115200.
886 EXPECT_EQ(115200, last_pipeline_statistics.video_memory_usage);
888 EXPECT_EQ(renderer_->GetPreferredRenderInterval(),
889 last_pipeline_statistics.video_frame_duration_average);
891 // Consider the case that rendering is faster than we setup the test event.
892 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will
893 // be called. And then during SatisfyPendingDecodeWithEndOfStream,
894 // BUFFER_HAVE_ENOUGH will be called again.
895 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
896 .Times(testing::AtMost(1));
897 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _))
898 .Times(testing::AtMost(1));
899 renderer_->OnTimeProgressing();
900 time_source_.StartTicking();
902 // Suspend all future callbacks and synthetically advance the media time,
903 // because this is a background render, we won't underflow by waiting until
904 // a pending read is ready.
905 null_video_sink_->set_background_render(true);
907 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(90)));
908 WaitForPendingDecode();
910 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_))
911 .WillOnce(SaveArg<0>(&last_pipeline_statistics));
912 SatisfyPendingDecodeWithEndOfStream();
917 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped);
918 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_decoded);
920 // Memory usage is relative, so the prior lines increased memory usage to
921 // 4 * 115200, so this last one should show we only have 1 frame left.
922 EXPECT_EQ(-3 * 115200, last_pipeline_statistics.video_memory_usage);
927 // Tests the case where underflow evicts all frames before EOS.
928 TEST_F(VideoRendererImplTest, UnderflowEvictionBeforeEOS) {
930 QueueFrames("0 30 60 90 100");
933 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
934 WaitableMessageLoopEvent event;
935 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
936 .WillOnce(RunOnceClosure(event.GetClosure()));
937 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(AnyNumber());
938 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
939 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
940 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
946 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
947 WaitableMessageLoopEvent event;
948 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _))
949 .WillOnce(RunOnceClosure(event.GetClosure()));
950 renderer_->OnTimeProgressing();
951 time_source_.StartTicking();
952 // Jump time far enough forward that no frames are valid.
953 AdvanceTimeInMs(1000);
957 WaitForPendingDecode();
959 renderer_->OnTimeStopped();
960 time_source_.StopTicking();
962 // Providing the end of stream packet should remove all frames and exit.
963 SatisfyPendingDecodeWithEndOfStream();
964 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
969 // Tests the case where underflow evicts all frames in the HAVE_ENOUGH state.
970 TEST_F(VideoRendererImplTest, UnderflowEvictionWhileHaveEnough) {
972 QueueFrames("0 30 60 90 100");
975 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
976 WaitableMessageLoopEvent event;
977 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
978 .WillOnce(RunOnceClosure(event.GetClosure()));
979 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(AnyNumber());
980 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
981 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
982 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
987 // Now wait until we have no effective frames.
989 SCOPED_TRACE("Waiting for zero effective frames.");
990 WaitableMessageLoopEvent event;
991 null_video_sink_->set_background_render(true);
992 time_source_.StartTicking();
993 AdvanceTimeInMs(1000);
994 renderer_->OnTimeProgressing();
995 EXPECT_CALL(mock_cb_, FrameReceived(_))
996 .WillOnce(RunOnceClosure(event.GetClosure()));
998 ASSERT_EQ(renderer_->effective_frames_queued_for_testing(), 0u);
1001 // When OnTimeStopped() is called it should transition to HAVE_NOTHING.
1003 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
1004 WaitableMessageLoopEvent event;
1005 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _))
1006 .WillOnce(RunOnceClosure(event.GetClosure()));
1007 renderer_->OnTimeStopped();
1014 TEST_F(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) {
1016 QueueFrames("0 30 60 90");
1018 WaitableMessageLoopEvent event;
1019 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1020 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
1021 .WillOnce(RunOnceClosure(event.GetClosure()));
1022 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1023 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1024 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1025 StartPlayingFrom(0);
1028 // Cycle ticking so that we get a non-null reference time.
1029 time_source_.StartTicking();
1030 time_source_.StopTicking();
1032 // Flush and simulate a seek past EOS, where some error prevents the decoder
1033 // from returning any frames.
1034 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _));
1037 StartPlayingFrom(200);
1038 WaitForPendingDecode();
1039 SatisfyPendingDecodeWithEndOfStream();
1040 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1045 TEST_F(VideoRendererImplTest, FramesAreNotExpiredDuringPreroll) {
1047 // !CanReadWithoutStalling() puts the renderer in state BUFFERING_HAVE_ENOUGH
1048 // after the first frame.
1049 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
1050 // Set background rendering to simulate the first couple of Render() calls
1052 null_video_sink_->set_background_render(true);
1053 QueueFrames("0 10 20");
1054 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
1055 .Times(testing::AtMost(1));
1056 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1057 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1058 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1059 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1060 StartPlayingFrom(0);
1062 renderer_->OnTimeProgressing();
1063 time_source_.StartTicking();
1065 WaitableMessageLoopEvent event;
1066 // Frame "10" should not have been expired.
1067 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(10)))
1068 .WillOnce(RunOnceClosure(event.GetClosure()));
1069 AdvanceTimeInMs(10);
1075 TEST_F(VideoRendererImplTest, VideoConfigChange) {
1078 // Configure demuxer stream to allow config changes.
1079 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
1080 .WillRepeatedly(Return(true));
1082 // Signal a config change at the next DemuxerStream::Read().
1083 DemuxerStream::DecoderBufferVector buffers;
1084 EXPECT_CALL(demuxer_stream_, OnRead(_))
1085 .WillOnce(RunOnceCallback<0>(DemuxerStream::kConfigChanged, buffers));
1087 // Use LargeEncrypted config (non-default) to ensure its plumbed through to
1089 demuxer_stream_.set_video_decoder_config(TestVideoConfig::LargeEncrypted());
1091 EXPECT_CALL(mock_cb_, OnVideoConfigChange(
1092 DecoderConfigEq(TestVideoConfig::LargeEncrypted())))
1095 // Start plyaing to trigger DemuxerStream::Read(), surfacing the config change
1096 StartPlayingFrom(0);
1101 TEST_F(VideoRendererImplTest, NaturalSizeChange) {
1104 gfx::Size initial_size(8, 8);
1105 gfx::Size larger_size(16, 16);
1107 QueueFrame(DecoderStatus::Codes::kOk,
1108 VideoFrame::CreateFrame(PIXEL_FORMAT_I420, initial_size,
1109 gfx::Rect(initial_size), initial_size,
1110 base::Milliseconds(0)));
1111 QueueFrame(DecoderStatus::Codes::kOk,
1112 VideoFrame::CreateFrame(PIXEL_FORMAT_I420, larger_size,
1113 gfx::Rect(larger_size), larger_size,
1114 base::Milliseconds(10)));
1115 QueueFrame(DecoderStatus::Codes::kOk,
1116 VideoFrame::CreateFrame(PIXEL_FORMAT_I420, larger_size,
1117 gfx::Rect(larger_size), larger_size,
1118 base::Milliseconds(20)));
1119 QueueFrame(DecoderStatus::Codes::kOk,
1120 VideoFrame::CreateFrame(PIXEL_FORMAT_I420, initial_size,
1121 gfx::Rect(initial_size), initial_size,
1122 base::Milliseconds(30)));
1124 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1125 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1126 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1129 // Callback is fired for the first frame.
1130 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(initial_size));
1131 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1132 StartPlayingFrom(0);
1133 renderer_->OnTimeProgressing();
1134 time_source_.StartTicking();
1137 // Callback should be fired once when switching to the larger size.
1138 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(larger_size));
1139 WaitableMessageLoopEvent event;
1140 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(10)))
1141 .WillOnce(RunOnceClosure(event.GetClosure()));
1142 AdvanceTimeInMs(10);
1146 // Called is not fired because frame size does not change.
1147 WaitableMessageLoopEvent event;
1148 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(20)))
1149 .WillOnce(RunOnceClosure(event.GetClosure()));
1150 AdvanceTimeInMs(10);
1154 // Callback is fired once when switching to the larger size.
1155 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(initial_size));
1156 WaitableMessageLoopEvent event;
1157 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(30)))
1158 .WillOnce(RunOnceClosure(event.GetClosure()));
1159 AdvanceTimeInMs(10);
1166 TEST_F(VideoRendererImplTest, OpacityChange) {
1169 gfx::Size frame_size(8, 8);
1170 VideoPixelFormat opaque_format = PIXEL_FORMAT_I420;
1171 VideoPixelFormat non_opaque_format = PIXEL_FORMAT_I420A;
1173 QueueFrame(DecoderStatus::Codes::kOk,
1174 VideoFrame::CreateFrame(non_opaque_format, frame_size,
1175 gfx::Rect(frame_size), frame_size,
1176 base::Milliseconds(0)));
1177 QueueFrame(DecoderStatus::Codes::kOk,
1178 VideoFrame::CreateFrame(non_opaque_format, frame_size,
1179 gfx::Rect(frame_size), frame_size,
1180 base::Milliseconds(10)));
1182 DecoderStatus::Codes::kOk,
1183 VideoFrame::CreateFrame(opaque_format, frame_size, gfx::Rect(frame_size),
1184 frame_size, base::Milliseconds(20)));
1186 DecoderStatus::Codes::kOk,
1187 VideoFrame::CreateFrame(opaque_format, frame_size, gfx::Rect(frame_size),
1188 frame_size, base::Milliseconds(30)));
1190 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1191 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1192 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(frame_size)).Times(1);
1195 // Callback is fired for the first frame.
1196 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(false));
1197 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1198 StartPlayingFrom(0);
1199 renderer_->OnTimeProgressing();
1200 time_source_.StartTicking();
1203 // Callback is not fired because opacity does not change.
1204 WaitableMessageLoopEvent event;
1205 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(10)))
1206 .WillOnce(RunOnceClosure(event.GetClosure()));
1207 AdvanceTimeInMs(10);
1211 // Called is fired when opacity changes.
1212 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(true));
1213 WaitableMessageLoopEvent event;
1214 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(20)))
1215 .WillOnce(RunOnceClosure(event.GetClosure()));
1216 AdvanceTimeInMs(10);
1220 // Callback is not fired because opacity does not change.
1221 WaitableMessageLoopEvent event;
1222 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(30)))
1223 .WillOnce(RunOnceClosure(event.GetClosure()));
1224 AdvanceTimeInMs(10);
1231 TEST_F(VideoRendererImplTest, VideoFrameRateChange) {
1234 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(AnyNumber());
1235 EXPECT_CALL(mock_cb_, OnBufferingStateChange(_, _)).Times(AnyNumber());
1236 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1237 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1238 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1240 // Send 50fps frames first.
1241 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(50)));
1242 QueueFrames("0 20 40 60 80 100 120 140 160 180 200");
1243 QueueFrames("220 240 260 280 300 320 340 360 380 400");
1245 // Also queue some frames that aren't at 50fps, so that we get an unknown fps.
1246 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>()));
1247 QueueFrames("500 600");
1249 // Drain everything.
1250 StartPlayingFrom(0);
1251 renderer_->OnTimeProgressing();
1252 time_source_.StartTicking();
1253 // Send in all the frames we queued.
1254 while (HasQueuedFrames()) {
1255 AdvanceTimeInMs(20);
1256 AdvanceWallclockTimeInMs(20);
1257 // This runs the sink callbacks to consume frames.
1258 task_environment_.FastForwardBy(base::Milliseconds(20));
1259 base::RunLoop().RunUntilIdle();
1265 class VideoRendererImplAsyncAddFrameReadyTest : public VideoRendererImplTest {
1267 void InitializeWithMockGpuMemoryBufferVideoFramePool() {
1268 renderer_ = std::make_unique<VideoRendererImpl>(
1269 base::SingleThreadTaskRunner::GetCurrentDefault(),
1270 null_video_sink_.get(),
1271 base::BindRepeating(&VideoRendererImplAsyncAddFrameReadyTest::
1272 CreateVideoDecodersForTest,
1273 base::Unretained(this)),
1275 std::make_unique<MockGpuMemoryBufferVideoFramePool>(&frame_ready_cbs_),
1277 VideoRendererImplTest::Initialize();
1281 std::vector<base::OnceClosure> frame_ready_cbs_;
1284 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) {
1285 InitializeWithMockGpuMemoryBufferVideoFramePool();
1286 QueueFrames("0 10 20 30");
1287 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1288 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1289 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1290 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1291 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1292 StartPlayingFrom(0);
1293 ASSERT_EQ(1u, frame_ready_cbs_.size());
1295 uint32_t frame_ready_index = 0;
1296 while (frame_ready_index < frame_ready_cbs_.size()) {
1297 std::move(frame_ready_cbs_[frame_ready_index++]).Run();
1298 base::RunLoop().RunUntilIdle();
1303 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, WeakFactoryDiscardsOneFrame) {
1304 InitializeWithMockGpuMemoryBufferVideoFramePool();
1305 QueueFrames("0 10 20 30");
1306 StartPlayingFrom(0);
1308 ASSERT_EQ(1u, frame_ready_cbs_.size());
1309 // This frame will be discarded.
1310 std::move(frame_ready_cbs_.front()).Run();
1314 enum class UnderflowTestType {
1315 // Renderer will require a default amount of buffering to reach HAVE_ENOUGH.
1317 // Both of these require only a single frame to reach HAVE_ENOUGH.
1319 CANT_READ_WITHOUT_STALLING
1323 : public VideoRendererImplTest,
1324 public testing::WithParamInterface<
1325 ::std::tuple<UnderflowTestType, BufferingStateChangeReason>> {
1327 void SetUp() override { std::tie(test_type, underflow_type) = GetParam(); }
1329 void TestBufferToHaveEnoughThenUnderflow() {
1330 InitializeWithLowDelay(test_type == UnderflowTestType::LOW_DELAY);
1332 if (test_type == UnderflowTestType::CANT_READ_WITHOUT_STALLING)
1333 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
1335 if (underflow_type == DEMUXER_UNDERFLOW) {
1336 simulate_demuxer_stall_after_n_reads_ = 4;
1338 QueueFrames("0 20 40 60");
1341 WaitableMessageLoopEvent event;
1342 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1343 EXPECT_CALL(mock_cb_,
1344 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
1345 BUFFERING_CHANGE_REASON_UNKNOWN))
1346 .WillOnce(RunOnceClosure(event.GetClosure()));
1347 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1348 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1349 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1350 StartPlayingFrom(0);
1352 Mock::VerifyAndClearExpectations(&mock_cb_);
1356 time_source_.StartTicking();
1357 renderer_->OnTimeProgressing();
1359 // Advance time slightly, but enough to exceed the duration of the last
1361 // Frames should be dropped and we should NOT signal having nothing.
1363 SCOPED_TRACE("Waiting for frame drops");
1364 WaitableMessageLoopEvent event;
1365 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(20))).Times(0);
1367 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(40))).Times(0);
1368 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(60)))
1369 .WillOnce(RunOnceClosure(event.GetClosure()));
1370 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1371 AdvanceTimeInMs(61);
1374 Mock::VerifyAndClearExpectations(&mock_cb_);
1377 // Advance time more. Now we should signal having nothing. And put
1378 // the last frame up for display.
1380 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
1381 WaitableMessageLoopEvent event;
1382 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
1384 .WillOnce(RunOnceClosure(event.GetClosure()));
1385 AdvanceTimeInMs(18);
1387 Mock::VerifyAndClearExpectations(&mock_cb_);
1390 EXPECT_EQ(1u, renderer_->frames_queued_for_testing());
1391 time_source_.StopTicking();
1392 renderer_->OnTimeStopped();
1393 EXPECT_EQ(0u, renderer_->frames_queued_for_testing());
1394 ASSERT_EQ(underflow_type == DEMUXER_UNDERFLOW, IsDemuxerStalled());
1395 ASSERT_EQ(underflow_type == DECODER_UNDERFLOW, IsDecodePending());
1397 // Stopping time signals a confirmed underflow to VRI. Verify updates to
1398 // buffering limits.
1399 switch (test_type) {
1400 // In the normal and cant_read modes, min and max buffered frames should
1401 // always be equal, and both should increase upon underflow.
1402 case UnderflowTestType::NORMAL:
1403 case UnderflowTestType::CANT_READ_WITHOUT_STALLING:
1404 EXPECT_EQ(renderer_->min_buffered_frames_for_testing(),
1405 limits::kMaxVideoFrames + 1);
1406 EXPECT_EQ(renderer_->max_buffered_frames_for_testing(),
1407 limits::kMaxVideoFrames + 1);
1409 // In low_delay mode only the max should increase while min remains 1.
1410 case UnderflowTestType::LOW_DELAY:
1411 EXPECT_EQ(renderer_->min_buffered_frames_for_testing(), 1);
1412 EXPECT_EQ(renderer_->max_buffered_frames_for_testing(),
1413 limits::kMaxVideoFrames + 1);
1418 UnderflowTestType test_type;
1419 BufferingStateChangeReason underflow_type;
1422 TEST_P(UnderflowTest, UnderflowAndEosTest) {
1423 TestBufferToHaveEnoughThenUnderflow();
1425 if (IsDemuxerStalled())
1428 // Receiving end of stream should signal having enough.
1430 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
1431 WaitableMessageLoopEvent event;
1432 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(AnyNumber());
1433 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1434 EXPECT_CALL(mock_cb_,
1435 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
1436 BUFFERING_CHANGE_REASON_UNKNOWN))
1437 .WillOnce(RunOnceClosure(event.GetClosure()));
1438 EXPECT_CALL(mock_cb_, OnEnded());
1439 SatisfyPendingDecodeWithEndOfStream();
1446 TEST_P(UnderflowTest, UnderflowAndRecoverTest) {
1447 TestBufferToHaveEnoughThenUnderflow();
1449 if (IsDemuxerStalled())
1452 // Queue some frames, satisfy reads, and make sure expired frames are gone
1453 // when the renderer paints the first frame.
1455 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
1456 WaitableMessageLoopEvent event;
1457 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(80))).Times(1);
1458 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1459 EXPECT_CALL(mock_cb_,
1460 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
1461 BUFFERING_CHANGE_REASON_UNKNOWN))
1462 .WillOnce(RunOnceClosure(event.GetClosure()));
1464 switch (test_type) {
1465 // In the normal underflow case we queue 5 frames here instead of four
1466 // since the underflow increases the number of required frames to reach
1467 // the have enough state.
1468 case UnderflowTestType::NORMAL:
1469 QueueFrames("80 100 120 140 160");
1470 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(50)));
1472 // In either of these modes the HAVE_ENOUGH transition should still
1473 // occur with a single frame.
1474 case UnderflowTestType::LOW_DELAY:
1475 case UnderflowTestType::CANT_READ_WITHOUT_STALLING:
1479 SatisfyPendingDecode();
1486 INSTANTIATE_TEST_SUITE_P(
1489 Combine(Values(UnderflowTestType::NORMAL,
1490 UnderflowTestType::LOW_DELAY,
1491 UnderflowTestType::CANT_READ_WITHOUT_STALLING),
1492 Values(DEMUXER_UNDERFLOW, DECODER_UNDERFLOW)));
1494 class VideoRendererLatencyHintTest : public VideoRendererImplTest {
1496 void VerifyDefaultRebufferingBehavior(int start_playing_from) {
1497 // Keep it simple. Only call this if you're starting from empty.
1498 DCHECK_EQ(renderer_->effective_frames_queued_for_testing(), 0u);
1500 // Initial frames should trigger various callbacks.
1501 EXPECT_CALL(mock_cb_,
1502 FrameReceived(HasTimestampMatcher(start_playing_from)));
1503 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1504 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(AnyNumber());
1505 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(AnyNumber());
1506 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(_)).Times(AnyNumber());
1508 // Queue 3 frames, 20 msec apart. Stop 1 shy of min_buffered_frames_.
1509 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 4);
1510 int frame_time = start_playing_from;
1511 for (int i = 0; i < 3; i++) {
1512 QueueFrames(base::NumberToString(frame_time));
1516 // Verify no transition to HAVE_ENOUGH since 3 < |min_buffered_frames_|
1517 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
1520 StartPlayingFrom(start_playing_from);
1521 base::RunLoop().RunUntilIdle();
1522 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 3u);
1523 Mock::VerifyAndClearExpectations(&mock_cb_);
1525 // Queuing one extra frame should trigger the transition.
1526 QueueFrames(base::NumberToString(frame_time));
1527 SatisfyPendingDecode();
1528 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1529 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(_)).Times(AnyNumber());
1530 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1531 base::RunLoop().RunUntilIdle();
1532 Mock::VerifyAndClearExpectations(&mock_cb_);
1536 // Test default HaveEnough transition when no latency hint is set.
1537 TEST_F(VideoRendererLatencyHintTest, HaveEnough_NoLatencyHint) {
1539 VerifyDefaultRebufferingBehavior(0);
1543 // Test early HaveEnough transition when low latency hint is set.
1544 TEST_F(VideoRendererLatencyHintTest, HaveEnough_LowLatencyHint) {
1547 // Set latencyHint to bare minimum.
1548 renderer_->SetLatencyHint(base::TimeDelta());
1550 // Initial frames should trigger various callbacks.
1551 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1552 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(2);
1553 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1554 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1555 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1557 // Only 1 frame should be needed to trigger have enough.
1558 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 1);
1561 StartPlayingFrom(0);
1562 base::RunLoop().RunUntilIdle();
1563 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 1u);
1564 Mock::VerifyAndClearExpectations(&mock_cb_);
1566 // Verify latency hint doesn't reduce our ability to buffer beyond the
1567 // 1-frame HAVE_ENOUGH (i.e. don't throttle decoding in the name of latency).
1568 EXPECT_EQ(renderer_->max_buffered_frames_for_testing(), 4);
1569 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(3);
1570 QueueFrames("10 20 30");
1571 WaitForPendingDecode();
1572 SatisfyPendingDecode();
1573 base::RunLoop().RunUntilIdle();
1574 EXPECT_EQ(renderer_->frames_queued_for_testing(), 4u);
1576 // Unset latencyHint, to verify default behavior.
1577 renderer_->SetLatencyHint(absl::nullopt);
1579 // Flush to return to clean slate.
1580 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _));
1583 VerifyDefaultRebufferingBehavior(1000);
1588 // Test late HaveEnough transition when high latency hint is set.
1589 TEST_F(VideoRendererLatencyHintTest, HaveEnough_HighLatencyHint) {
1590 // We must provide a |buffer_duration_| for the latencyHint to take effect
1591 // immediately. The VideoRendererAlgorithm will eventually provide a PTS-delta
1592 // duration, but not until after we've started rendering.
1593 buffer_duration_ = base::Milliseconds(30);
1595 // Set latencyHint to a large value.
1596 renderer_->SetLatencyHint(base::Milliseconds(400));
1598 // NOTE: other tests will SetLatencyHint after Initialize(). Either way should
1599 // work. Initializing later is especially interesting for "high" hints because
1600 // the renderer will try to set buffering caps based on stream state that
1601 // isn't yet available.
1604 // Initial frames should trigger various callbacks.
1605 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1606 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1607 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1608 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1610 // Queue 12 frames, each 30 ms apart. At this framerate, 400ms rounds to 13
1611 // frames, so 12 frames should be 1 shy of the HaveEnough threshold.
1612 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(33)));
1613 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
1615 QueueFrames("0 30 60 90 120 150 180 210 240 270 300 330");
1617 StartPlayingFrom(0);
1618 base::RunLoop().RunUntilIdle();
1619 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 13);
1620 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 12u);
1621 Mock::VerifyAndClearExpectations(&mock_cb_);
1623 // Queue 1 additional frame and verify HaveEnough threshold is reached.
1624 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1625 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1627 SatisfyPendingDecode();
1628 base::RunLoop().RunUntilIdle();
1629 Mock::VerifyAndClearExpectations(&mock_cb_);
1631 // Unset latencyHint, to verify default behavior.
1632 renderer_->SetLatencyHint(absl::nullopt);
1634 // Flush to return to clean slate.
1635 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _));
1637 Mock::VerifyAndClearExpectations(&mock_cb_);
1639 VerifyDefaultRebufferingBehavior(1000);
1644 // Test updates to buffering limits upon underflow when latency hint set.
1645 TEST_F(VideoRendererLatencyHintTest,
1646 LatencyHintUnderflowUpdatesMaxBufferingLimit) {
1647 // Enable low delay mode. Low delay mode is tested separately.
1648 InitializeWithLowDelay(true);
1649 EXPECT_EQ(renderer_->min_buffered_frames_for_testing(), 1);
1651 // We must provide a |buffer_duration_| for the latencyHint to take effect
1652 // immediately. The VideoRendererAlgorithm will eventually provide a PTS-delta
1653 // duration, but not until after we've started rendering.
1654 buffer_duration_ = base::Milliseconds(30);
1656 // Set latency hint to a medium value.
1657 renderer_->SetLatencyHint(base::Milliseconds(200));
1659 // Stall the demuxer after 7 frames.
1660 simulate_demuxer_stall_after_n_reads_ = 7;
1662 // Queue up enough frames to trigger HAVE_ENOUGH. Each frame is 30 ms apart.
1663 // At this spacing, 200ms rounds to 7 frames.
1664 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1665 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1666 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1667 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1668 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(33)));
1669 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1670 QueueFrames("0 30 60 90 120 150 180");
1671 StartPlayingFrom(0);
1672 base::RunLoop().RunUntilIdle();
1673 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 7);
1674 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 7u);
1675 Mock::VerifyAndClearExpectations(&mock_cb_);
1677 // Advance time to trigger HAVE_NOTHING (underflow).
1679 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
1680 WaitableMessageLoopEvent event;
1681 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(180)));
1682 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
1684 .WillOnce(RunOnceClosure(event.GetClosure()));
1685 renderer_->OnTimeProgressing();
1686 time_source_.StartTicking();
1687 AdvanceTimeInMs(300);
1689 Mock::VerifyAndClearExpectations(&mock_cb_);
1692 // Simulate delayed buffering state callbacks.
1693 time_source_.StopTicking();
1694 renderer_->OnTimeStopped();
1696 // When latency hint set the max should increase while min remains steady
1697 // (user controls the min via hint).
1698 EXPECT_EQ(renderer_->min_buffered_frames_for_testing(), 7);
1699 EXPECT_EQ(renderer_->max_buffered_frames_for_testing(), 7 + 1);
1704 // Test that latency hint overrides low delay mode.
1705 TEST_F(VideoRendererLatencyHintTest, LatencyHintOverridesLowDelay) {
1706 // Enable low delay mode. Low delay mode is tested separately.
1707 InitializeWithLowDelay(true);
1708 EXPECT_EQ(renderer_->min_buffered_frames_for_testing(), 1);
1710 // We must provide a |buffer_duration_| for the latencyHint to take effect
1711 // immediately. The VideoRendererAlgorithm will eventually provide a PTS-delta
1712 // duration, but not until after we've started rendering.
1713 buffer_duration_ = base::Milliseconds(30);
1715 // Set latency hint to a medium value.
1716 renderer_->SetLatencyHint(base::Milliseconds(200));
1718 // Initial frames should trigger various callbacks.
1719 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1720 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1721 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1722 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1724 // Queue 6 frames, each 30 ms apart. At this spacing, 200ms rounds to
1725 // 7 frames, so 6 frames should be 1 shy of the HaveEnough threshold. Verify
1726 // that HAVE_ENOUGH is not triggered in spite of being initialized with low
1728 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(absl::optional<int>(33)));
1729 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
1731 QueueFrames("0 30 60 90 120 150");
1732 StartPlayingFrom(0);
1733 base::RunLoop().RunUntilIdle();
1734 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 7);
1735 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 6u);
1736 Mock::VerifyAndClearExpectations(&mock_cb_);
1738 // Queue 1 additional frame and verify HaveEnough threshold is reached.
1739 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1740 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1742 SatisfyPendingDecode();
1743 base::RunLoop().RunUntilIdle();
1744 Mock::VerifyAndClearExpectations(&mock_cb_);
1746 // Unset latencyHint, to verify default behavior. NOTE: low delay mode is not
1747 // restored when latency hint unset.
1748 renderer_->SetLatencyHint(absl::nullopt);
1750 // Flush to return to clean slate.
1751 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _));
1753 Mock::VerifyAndClearExpectations(&mock_cb_);
1755 VerifyDefaultRebufferingBehavior(1000);
1760 // Test that !CanReadWithoutStalling() overrides latency hint.
1761 TEST_F(VideoRendererLatencyHintTest,
1762 CantReadWithoutStallingOverridesLatencyHint) {
1765 // Let decoder indicate that it CANT read without stalling, meaning we should
1766 // enter HAVE_ENOUGH with just one effective frame (waiting for more frames
1767 // will stall the decoder).
1768 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
1770 // We must provide a |buffer_duration_| for the latencyHint to take effect
1771 // immediately. The VideoRendererAlgorithm will eventually provide a PTS-delta
1772 // duration, but not until after we've started rendering.
1773 buffer_duration_ = base::Milliseconds(30);
1775 // Set latency hint to a medium value. At a spacing of 30ms this would set
1776 // the HAVE_ENOUGH threshold to 4 frames.
1777 renderer_->SetLatencyHint(base::Milliseconds(200));
1779 // Initial frames should trigger various callbacks.
1780 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(0)));
1781 EXPECT_CALL(mock_cb_, OnVideoNaturalSizeChange(_)).Times(1);
1782 EXPECT_CALL(mock_cb_, OnVideoOpacityChange(_)).Times(1);
1783 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1785 // Queue 1 frame. This is well short of what the latency hint would require,
1786 // but we CANT READ WITHOUT STALLING, so expect a transition to HAVE_ENOUGH
1787 // after just 1 frame.
1788 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1790 StartPlayingFrom(0);
1791 base::RunLoop().RunUntilIdle();
1792 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 7);
1793 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 1u);
1794 Mock::VerifyAndClearExpectations(&mock_cb_);
1796 // Queue some additional frames, verify buffering state holds at HAVE_ENOUGH.
1797 QueueFrames("30 60 90 120");
1798 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1799 EXPECT_CALL(mock_cb_, OnBufferingStateChange(_, _)).Times(0);
1800 // SatisfyPendingDecode();
1801 base::RunLoop().RunUntilIdle();
1802 Mock::VerifyAndClearExpectations(&mock_cb_);
1804 // Unset latency hint to verify 1-frame HAVE_ENOUGH threshold is maintained.
1805 renderer_->SetLatencyHint(absl::nullopt);
1807 // Flush to return to clean slate.
1808 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING, _));
1810 Mock::VerifyAndClearExpectations(&mock_cb_);
1812 // Expect HAVE_ENOUGH (and various other callbacks) again.
1813 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _));
1814 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestampMatcher(1000)));
1815 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber());
1816 EXPECT_CALL(mock_cb_, OnVideoFrameRateChange(_)).Times(AnyNumber());
1819 QueueFrames("1000");
1820 StartPlayingFrom(1000);
1821 base::RunLoop().RunUntilIdle();
1822 ASSERT_EQ(renderer_->min_buffered_frames_for_testing(), 4);
1823 EXPECT_EQ(renderer_->effective_frames_queued_for_testing(), 1u);
1824 Mock::VerifyAndClearExpectations(&mock_cb_);
1829 } // namespace media