1 // Copyright 2017 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.
4
5 #include "third_party/blink/renderer/platform/graphics/video_frame_submitter.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/read_only_shared_memory_region.h"
15 #include "base/test/bind_test_util.h"
16 #include "base/test/simple_test_tick_clock.h"
17 #include "base/test/task_environment.h"
18 #include "base/time/time.h"
19 #include "cc/layers/video_frame_provider.h"
20 #include "cc/metrics/video_playback_roughness_reporter.h"
21 #include "cc/test/layer_test_common.h"
22 #include "cc/trees/layer_tree_settings.h"
23 #include "cc/trees/task_runner_provider.h"
24 #include "components/viz/test/fake_external_begin_frame_source.h"
25 #include "components/viz/test/test_context_provider.h"
26 #include "media/base/video_frame.h"
27 #include "mojo/public/cpp/bindings/pending_receiver.h"
28 #include "mojo/public/cpp/bindings/pending_remote.h"
29 #include "mojo/public/cpp/bindings/receiver.h"
30 #include "mojo/public/cpp/bindings/remote.h"
31 #include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
32 #include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h"
36 #include "third_party/blink/renderer/platform/graphics/test/mock_embedded_frame_sink_provider.h"
37 #include "third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h"
38 #include "third_party/blink/renderer/platform/wtf/functional.h"
39
40 using testing::_;
41 using testing::AnyNumber;
42 using testing::Invoke;
43 using testing::Return;
44 using testing::StrictMock;
45
46 namespace blink {
47
48 namespace {
49
50 class MockVideoFrameProvider : public cc::VideoFrameProvider {
51 public:
52 MockVideoFrameProvider() = default;
53 ~MockVideoFrameProvider() override = default;
54
55 MOCK_METHOD1(SetVideoFrameProviderClient, void(Client*));
56 MOCK_METHOD2(UpdateCurrentFrame, bool(base::TimeTicks, base::TimeTicks));
57 MOCK_METHOD0(HasCurrentFrame, bool());
58 MOCK_METHOD0(GetCurrentFrame, scoped_refptr<media::VideoFrame>());
59 MOCK_METHOD0(PutCurrentFrame, void());
60
GetPreferredRenderInterval()61 base::TimeDelta GetPreferredRenderInterval() override {
62 return preferred_interval;
63 }
64
65 base::TimeDelta preferred_interval;
66
67 private:
68 DISALLOW_COPY_AND_ASSIGN(MockVideoFrameProvider);
69 };
70
71 class VideoMockCompositorFrameSink
72 : public viz::mojom::blink::CompositorFrameSink {
73 public:
VideoMockCompositorFrameSink(mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSink> receiver)74 VideoMockCompositorFrameSink(
75 mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSink> receiver) {
76 receiver_.Bind(std::move(receiver));
77 }
78 ~VideoMockCompositorFrameSink() override = default;
79
last_submitted_compositor_frame() const80 const viz::CompositorFrame& last_submitted_compositor_frame() const {
81 return last_submitted_compositor_frame_;
82 }
83
84 MOCK_METHOD1(SetNeedsBeginFrame, void(bool));
85 MOCK_METHOD0(SetWantsAnimateOnlyBeginFrames, void());
86
87 MOCK_METHOD2(DoSubmitCompositorFrame,
88 void(const viz::LocalSurfaceId&, viz::CompositorFrame*));
SubmitCompositorFrame(const viz::LocalSurfaceId & id,viz::CompositorFrame frame,viz::mojom::blink::HitTestRegionListPtr hit_test_region_list,uint64_t submit_time)89 void SubmitCompositorFrame(
90 const viz::LocalSurfaceId& id,
91 viz::CompositorFrame frame,
92 viz::mojom::blink::HitTestRegionListPtr hit_test_region_list,
93 uint64_t submit_time) override {
94 last_submitted_compositor_frame_ = std::move(frame);
95 DoSubmitCompositorFrame(id, &last_submitted_compositor_frame_);
96 }
SubmitCompositorFrameSync(const viz::LocalSurfaceId & id,viz::CompositorFrame frame,viz::mojom::blink::HitTestRegionListPtr hit_test_region_list,uint64_t submit_time,const SubmitCompositorFrameSyncCallback callback)97 void SubmitCompositorFrameSync(
98 const viz::LocalSurfaceId& id,
99 viz::CompositorFrame frame,
100 viz::mojom::blink::HitTestRegionListPtr hit_test_region_list,
101 uint64_t submit_time,
102 const SubmitCompositorFrameSyncCallback callback) override {
103 last_submitted_compositor_frame_ = std::move(frame);
104 DoSubmitCompositorFrame(id, &last_submitted_compositor_frame_);
105 }
106
107 MOCK_METHOD1(DidNotProduceFrame, void(const viz::BeginFrameAck&));
108
109 MOCK_METHOD2(DidAllocateSharedBitmap_,
110 void(base::ReadOnlySharedMemoryRegion* region,
111 gpu::mojom::blink::MailboxPtr* id));
DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,gpu::mojom::blink::MailboxPtr id)112 void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
113 gpu::mojom::blink::MailboxPtr id) override {
114 DidAllocateSharedBitmap_(®ion, &id);
115 }
116
117 MOCK_METHOD1(DidDeleteSharedBitmap_, void(gpu::mojom::blink::MailboxPtr* id));
DidDeleteSharedBitmap(gpu::mojom::blink::MailboxPtr id)118 void DidDeleteSharedBitmap(gpu::mojom::blink::MailboxPtr id) override {
119 DidDeleteSharedBitmap_(&id);
120 }
121
122 private:
123 mojo::Receiver<viz::mojom::blink::CompositorFrameSink> receiver_{this};
124
125 viz::CompositorFrame last_submitted_compositor_frame_;
126
127 DISALLOW_COPY_AND_ASSIGN(VideoMockCompositorFrameSink);
128 };
129
130 class MockVideoFrameResourceProvider
131 : public blink::VideoFrameResourceProvider {
132 public:
MockVideoFrameResourceProvider(viz::RasterContextProvider * context_provider,viz::SharedBitmapReporter * shared_bitmap_reporter)133 MockVideoFrameResourceProvider(
134 viz::RasterContextProvider* context_provider,
135 viz::SharedBitmapReporter* shared_bitmap_reporter)
136 : blink::VideoFrameResourceProvider(cc::LayerTreeSettings(), false) {
137 blink::VideoFrameResourceProvider::Initialize(context_provider,
138 shared_bitmap_reporter);
139 }
140 ~MockVideoFrameResourceProvider() override = default;
141
142 MOCK_METHOD2(Initialize,
143 void(viz::RasterContextProvider*, viz::SharedBitmapReporter*));
144 MOCK_METHOD4(AppendQuads,
145 void(viz::RenderPass*,
146 scoped_refptr<media::VideoFrame>,
147 media::VideoRotation,
148 bool));
149 MOCK_METHOD0(ReleaseFrameResources, void());
150 MOCK_METHOD2(PrepareSendToParent,
151 void(const WebVector<viz::ResourceId>&,
152 WebVector<viz::TransferableResource>*));
153 MOCK_METHOD1(
154 ReceiveReturnsFromParent,
155 void(const Vector<viz::ReturnedResource>& transferable_resources));
156 MOCK_METHOD0(ObtainContextProvider, void());
157
158 private:
159 DISALLOW_COPY_AND_ASSIGN(MockVideoFrameResourceProvider);
160 };
161 } // namespace
162
163 class VideoFrameSubmitterTest : public testing::Test {
164 public:
VideoFrameSubmitterTest()165 VideoFrameSubmitterTest()
166 : now_src_(new base::SimpleTestTickClock()),
167 begin_frame_source_(new viz::FakeExternalBeginFrameSource(0.f, false)),
168 video_frame_provider_(new StrictMock<MockVideoFrameProvider>()),
169 context_provider_(viz::TestContextProvider::Create()) {
170 context_provider_->BindToCurrentThread();
171 MakeSubmitter();
172 task_environment_.RunUntilIdle();
173 }
174
MakeSubmitter()175 void MakeSubmitter() { MakeSubmitter(base::DoNothing()); }
176
MakeSubmitter(cc::PlaybackRoughnessReportingCallback reporting_cb)177 void MakeSubmitter(cc::PlaybackRoughnessReportingCallback reporting_cb) {
178 resource_provider_ = new StrictMock<MockVideoFrameResourceProvider>(
179 context_provider_.get(), nullptr);
180 submitter_ = std::make_unique<VideoFrameSubmitter>(
181 base::DoNothing(), reporting_cb,
182 base::WrapUnique<MockVideoFrameResourceProvider>(resource_provider_));
183
184 submitter_->Initialize(video_frame_provider_.get());
185 mojo::PendingRemote<viz::mojom::blink::CompositorFrameSink> submitter_sink;
186 sink_ = std::make_unique<StrictMock<VideoMockCompositorFrameSink>>(
187 submitter_sink.InitWithNewPipeAndPassReceiver());
188
189 // By setting the submission state before we set the sink, we can make
190 // testing easier without having to worry about the first sent frame.
191 submitter_->SetIsSurfaceVisible(true);
192 submitter_->compositor_frame_sink_.Bind(std::move(submitter_sink));
193 mojo::Remote<mojom::blink::SurfaceEmbedder> embedder;
194 ignore_result(embedder.BindNewPipeAndPassReceiver());
195 submitter_->surface_embedder_ = std::move(embedder);
196 auto surface_id = viz::SurfaceId(
197 viz::FrameSinkId(1, 1),
198 viz::LocalSurfaceId(11,
199 base::UnguessableToken::Deserialize(0x111111, 0)));
200 submitter_->frame_sink_id_ = surface_id.frame_sink_id();
201 submitter_->child_local_surface_id_allocator_.UpdateFromParent(
202 viz::LocalSurfaceIdAllocation(surface_id.local_surface_id(),
203 base::TimeTicks::Now()));
204 }
205
IsRendering() const206 bool IsRendering() const { return submitter_->is_rendering_; }
207
GetProvider() const208 cc::VideoFrameProvider* GetProvider() const {
209 return submitter_->video_frame_provider_;
210 }
211
ShouldSubmit() const212 bool ShouldSubmit() const { return submitter_->ShouldSubmit(); }
213
SubmitSingleFrame()214 void SubmitSingleFrame() { submitter_->SubmitSingleFrame(); }
215
child_local_surface_id_allocator() const216 const viz::ChildLocalSurfaceIdAllocator& child_local_surface_id_allocator()
217 const {
218 return submitter_->child_local_surface_id_allocator_;
219 }
220
frame_size() const221 gfx::Size frame_size() const { return submitter_->frame_size_; }
222
OnReceivedContextProvider(bool use_gpu_compositing,scoped_refptr<viz::RasterContextProvider> context_provider)223 void OnReceivedContextProvider(
224 bool use_gpu_compositing,
225 scoped_refptr<viz::RasterContextProvider> context_provider) {
226 submitter_->OnReceivedContextProvider(use_gpu_compositing,
227 std::move(context_provider));
228 }
229
AckSubmittedFrame()230 void AckSubmittedFrame() {
231 WTF::Vector<viz::ReturnedResource> resources;
232 EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
233 submitter_->DidReceiveCompositorFrameAck(resources);
234 }
235
236 protected:
237 base::test::TaskEnvironment task_environment_;
238 std::unique_ptr<base::SimpleTestTickClock> now_src_;
239 std::unique_ptr<viz::FakeExternalBeginFrameSource> begin_frame_source_;
240 std::unique_ptr<StrictMock<VideoMockCompositorFrameSink>> sink_;
241 std::unique_ptr<StrictMock<MockVideoFrameProvider>> video_frame_provider_;
242 StrictMock<MockVideoFrameResourceProvider>* resource_provider_;
243 scoped_refptr<viz::TestContextProvider> context_provider_;
244 std::unique_ptr<VideoFrameSubmitter> submitter_;
245 };
246
247 enum class SubmissionType {
248 kBeginFrame,
249 kStateChange,
250 kManual,
251 };
252
253 #define EXPECT_GET_PUT_FRAME() \
254 do { \
255 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) \
256 .WillOnce(Return(media::VideoFrame::CreateFrame( \
257 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), \
258 gfx::Rect(gfx::Size(8, 8)), gfx::Size(8, 8), base::TimeDelta()))); \
259 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); \
260 } while (0)
261
262 // Create submission state macro to ease complexity. Use a macro instead of a
263 // function so that line numbers are useful in test failures.
264 #define EXPECT_SUBMISSION(type) \
265 do { \
266 if (type == SubmissionType::kBeginFrame) { \
267 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _)) \
268 .WillOnce(Return(true)); \
269 } \
270 EXPECT_GET_PUT_FRAME(); \
271 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)); \
272 EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _)); \
273 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); \
274 EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); \
275 } while (0)
276
TEST_F(VideoFrameSubmitterTest,StatRenderingFlipsBits)277 TEST_F(VideoFrameSubmitterTest, StatRenderingFlipsBits) {
278 EXPECT_FALSE(IsRendering());
279 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
280
281 submitter_->StartRendering();
282
283 task_environment_.RunUntilIdle();
284
285 EXPECT_TRUE(IsRendering());
286 }
287
TEST_F(VideoFrameSubmitterTest,StopRenderingSkipsUpdateCurrentFrame)288 TEST_F(VideoFrameSubmitterTest, StopRenderingSkipsUpdateCurrentFrame) {
289 EXPECT_FALSE(IsRendering());
290 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
291
292 submitter_->StartRendering();
293
294 task_environment_.RunUntilIdle();
295
296 EXPECT_TRUE(IsRendering());
297
298 // OnBeginFrame() submits one frame.
299 EXPECT_SUBMISSION(SubmissionType::kBeginFrame);
300 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
301 BEGINFRAME_FROM_HERE, now_src_.get());
302 submitter_->OnBeginFrame(args, {});
303 task_environment_.RunUntilIdle();
304 AckSubmittedFrame();
305
306 // StopRendering submits one more frame.
307 EXPECT_SUBMISSION(SubmissionType::kStateChange);
308 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
309 submitter_->StopRendering();
310 task_environment_.RunUntilIdle();
311 AckSubmittedFrame();
312
313 // No frames should be produced after StopRendering().
314 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
315 args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
316 now_src_.get());
317 submitter_->OnBeginFrame(args, {});
318 task_environment_.RunUntilIdle();
319 }
320
TEST_F(VideoFrameSubmitterTest,StopUsingProviderNullsProvider)321 TEST_F(VideoFrameSubmitterTest, StopUsingProviderNullsProvider) {
322 EXPECT_FALSE(IsRendering());
323 EXPECT_EQ(video_frame_provider_.get(), GetProvider());
324
325 submitter_->StopUsingProvider();
326
327 EXPECT_EQ(nullptr, GetProvider());
328 }
329
TEST_F(VideoFrameSubmitterTest,StopUsingProviderSubmitsFrameAndStopsRendering)330 TEST_F(VideoFrameSubmitterTest,
331 StopUsingProviderSubmitsFrameAndStopsRendering) {
332 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
333 submitter_->StartRendering();
334 task_environment_.RunUntilIdle();
335
336 EXPECT_TRUE(IsRendering());
337
338 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
339 EXPECT_SUBMISSION(SubmissionType::kStateChange);
340 submitter_->StopUsingProvider();
341
342 task_environment_.RunUntilIdle();
343
344 EXPECT_FALSE(IsRendering());
345 }
346
TEST_F(VideoFrameSubmitterTest,DidReceiveFrameStillSubmitsIfRendering)347 TEST_F(VideoFrameSubmitterTest, DidReceiveFrameStillSubmitsIfRendering) {
348 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
349
350 submitter_->StartRendering();
351 task_environment_.RunUntilIdle();
352
353 EXPECT_TRUE(IsRendering());
354
355 EXPECT_SUBMISSION(SubmissionType::kManual);
356 submitter_->DidReceiveFrame();
357 task_environment_.RunUntilIdle();
358 }
359
TEST_F(VideoFrameSubmitterTest,DidReceiveFrameSubmitsFrame)360 TEST_F(VideoFrameSubmitterTest, DidReceiveFrameSubmitsFrame) {
361 EXPECT_FALSE(IsRendering());
362
363 EXPECT_SUBMISSION(SubmissionType::kManual);
364 submitter_->DidReceiveFrame();
365 task_environment_.RunUntilIdle();
366 }
367
TEST_F(VideoFrameSubmitterTest,ShouldSubmitPreventsSubmission)368 TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
369 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
370 submitter_->SetIsSurfaceVisible(false);
371 task_environment_.RunUntilIdle();
372
373 EXPECT_FALSE(ShouldSubmit());
374
375 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
376 submitter_->StartRendering();
377 task_environment_.RunUntilIdle();
378
379 EXPECT_SUBMISSION(SubmissionType::kStateChange);
380 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
381 submitter_->SetIsSurfaceVisible(true);
382 task_environment_.RunUntilIdle();
383 AckSubmittedFrame();
384
385 EXPECT_TRUE(ShouldSubmit());
386
387 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
388 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).Times(0);
389 submitter_->SetIsSurfaceVisible(false);
390 task_environment_.RunUntilIdle();
391
392 EXPECT_FALSE(ShouldSubmit());
393
394 // We should only see a GetCurrentFrame() without a PutCurrentFrame() since
395 // we drop the submission because !ShouldSubmit().
396 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
397 .WillOnce(Return(media::VideoFrame::CreateFrame(
398 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
399 gfx::Size(8, 8), base::TimeDelta())));
400
401 SubmitSingleFrame();
402 }
403
404 // Tests that when set to true SetForceSubmit forces frame submissions.
405 // regardless of the internal submit state.
TEST_F(VideoFrameSubmitterTest,SetForceSubmitForcesSubmission)406 TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
407 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
408 submitter_->SetIsSurfaceVisible(false);
409 task_environment_.RunUntilIdle();
410
411 EXPECT_FALSE(ShouldSubmit());
412
413 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
414 EXPECT_SUBMISSION(SubmissionType::kStateChange);
415 submitter_->SetForceSubmit(true);
416 AckSubmittedFrame();
417
418 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
419 submitter_->StartRendering();
420 task_environment_.RunUntilIdle();
421
422 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
423 EXPECT_SUBMISSION(SubmissionType::kStateChange);
424 submitter_->SetIsSurfaceVisible(true);
425 task_environment_.RunUntilIdle();
426 EXPECT_TRUE(ShouldSubmit());
427 AckSubmittedFrame();
428
429 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
430 EXPECT_SUBMISSION(SubmissionType::kStateChange);
431 submitter_->SetIsSurfaceVisible(false);
432 task_environment_.RunUntilIdle();
433 EXPECT_TRUE(ShouldSubmit());
434 AckSubmittedFrame();
435
436 EXPECT_SUBMISSION(SubmissionType::kManual);
437 SubmitSingleFrame();
438 task_environment_.RunUntilIdle();
439 }
440
TEST_F(VideoFrameSubmitterTest,RotationInformationPassedToResourceProvider)441 TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
442 // Check to see if rotation is communicated pre-rendering.
443 EXPECT_FALSE(IsRendering());
444
445 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_90);
446
447 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
448 .WillOnce(Return(media::VideoFrame::CreateFrame(
449 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
450 gfx::Size(8, 8), base::TimeDelta())));
451 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
452 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
453 EXPECT_CALL(*resource_provider_,
454 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90, _));
455 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
456 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
457
458 submitter_->DidReceiveFrame();
459 task_environment_.RunUntilIdle();
460 AckSubmittedFrame();
461
462 // Check to see if an update to rotation just before rendering is
463 // communicated.
464 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_180);
465
466 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
467 submitter_->StartRendering();
468 task_environment_.RunUntilIdle();
469 AckSubmittedFrame();
470
471 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
472 .WillOnce(Return(true));
473 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
474 .WillOnce(Return(media::VideoFrame::CreateFrame(
475 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
476 gfx::Size(8, 8), base::TimeDelta())));
477 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
478 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
479 EXPECT_CALL(*resource_provider_,
480 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180, _));
481 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
482 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
483
484 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
485 BEGINFRAME_FROM_HERE, now_src_.get());
486 submitter_->OnBeginFrame(args, {});
487 task_environment_.RunUntilIdle();
488 AckSubmittedFrame();
489
490 // Check to see if changing rotation while rendering is handled.
491 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_270);
492
493 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
494 .WillOnce(Return(true));
495 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
496 .WillOnce(Return(media::VideoFrame::CreateFrame(
497 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
498 gfx::Size(8, 8), base::TimeDelta())));
499 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
500 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
501 EXPECT_CALL(*resource_provider_,
502 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270, _));
503 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
504 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
505
506 args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
507 now_src_.get());
508 submitter_->OnBeginFrame(args, {});
509 task_environment_.RunUntilIdle();
510 }
511
TEST_F(VideoFrameSubmitterTest,OnBeginFrameSubmitsFrame)512 TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) {
513 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
514
515 submitter_->StartRendering();
516 task_environment_.RunUntilIdle();
517
518 EXPECT_SUBMISSION(SubmissionType::kBeginFrame);
519 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
520 BEGINFRAME_FROM_HERE, now_src_.get());
521 submitter_->OnBeginFrame(args, {});
522 task_environment_.RunUntilIdle();
523 }
524
TEST_F(VideoFrameSubmitterTest,MissedFrameArgDoesNotProduceFrame)525 TEST_F(VideoFrameSubmitterTest, MissedFrameArgDoesNotProduceFrame) {
526 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
527
528 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
529 BEGINFRAME_FROM_HERE, now_src_.get());
530 args.type = viz::BeginFrameArgs::MISSED;
531 submitter_->OnBeginFrame(args, {});
532 task_environment_.RunUntilIdle();
533 }
534
TEST_F(VideoFrameSubmitterTest,MissingProviderDoesNotProduceFrame)535 TEST_F(VideoFrameSubmitterTest, MissingProviderDoesNotProduceFrame) {
536 submitter_->StopUsingProvider();
537
538 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
539
540 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
541 BEGINFRAME_FROM_HERE, now_src_.get());
542 submitter_->OnBeginFrame(args, {});
543 task_environment_.RunUntilIdle();
544 }
545
TEST_F(VideoFrameSubmitterTest,NoUpdateOnFrameDoesNotProduceFrame)546 TEST_F(VideoFrameSubmitterTest, NoUpdateOnFrameDoesNotProduceFrame) {
547 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
548 submitter_->StartRendering();
549
550 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
551 .WillOnce(Return(false));
552 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
553
554 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
555 BEGINFRAME_FROM_HERE, now_src_.get());
556 submitter_->OnBeginFrame(args, {});
557 task_environment_.RunUntilIdle();
558 }
559
TEST_F(VideoFrameSubmitterTest,NotRenderingDoesNotProduceFrame)560 TEST_F(VideoFrameSubmitterTest, NotRenderingDoesNotProduceFrame) {
561 // We don't care if UpdateCurrentFrame is called or not; it doesn't matter
562 // if we're not rendering.
563 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
564 .Times(AnyNumber());
565 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
566
567 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
568 BEGINFRAME_FROM_HERE, now_src_.get());
569 submitter_->OnBeginFrame(args, {});
570 task_environment_.RunUntilIdle();
571 }
572
TEST_F(VideoFrameSubmitterTest,ReturnsResourceOnCompositorAck)573 TEST_F(VideoFrameSubmitterTest, ReturnsResourceOnCompositorAck) {
574 AckSubmittedFrame();
575 task_environment_.RunUntilIdle();
576 }
577
578 // Tests that after submitting a frame, no frame will be submitted until an ACK
579 // was received. This is tested by simulating another BeginFrame message.
TEST_F(VideoFrameSubmitterTest,WaitingForAckPreventsNewFrame)580 TEST_F(VideoFrameSubmitterTest, WaitingForAckPreventsNewFrame) {
581 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
582
583 submitter_->StartRendering();
584 task_environment_.RunUntilIdle();
585
586 EXPECT_SUBMISSION(SubmissionType::kBeginFrame);
587 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
588 BEGINFRAME_FROM_HERE, now_src_.get());
589 submitter_->OnBeginFrame(args, {});
590 task_environment_.RunUntilIdle();
591
592 // DidNotProduceFrame should be called because no frame will be submitted
593 // given that the ACK is still pending.
594 EXPECT_CALL(*sink_, DidNotProduceFrame(_)).Times(1);
595
596 // UpdateCurrentFrame should still be called, however, so that the compositor
597 // knows that we missed a frame.
598 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _)).Times(1);
599
600 std::unique_ptr<base::SimpleTestTickClock> new_time =
601 std::make_unique<base::SimpleTestTickClock>();
602 args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
603 new_time.get());
604 submitter_->OnBeginFrame(args, {});
605 task_environment_.RunUntilIdle();
606 }
607
608 // Similar to above but verifies the single-frame paint path.
TEST_F(VideoFrameSubmitterTest,WaitingForAckPreventsSubmitSingleFrame)609 TEST_F(VideoFrameSubmitterTest, WaitingForAckPreventsSubmitSingleFrame) {
610 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
611
612 submitter_->StartRendering();
613 task_environment_.RunUntilIdle();
614
615 EXPECT_SUBMISSION(SubmissionType::kManual);
616 submitter_->DidReceiveFrame();
617 task_environment_.RunUntilIdle();
618
619 // GetCurrentFrame() should be called, but PutCurrentFrame() should not, since
620 // the frame is dropped waiting for the ack.
621 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
622 .WillOnce(Return(media::VideoFrame::CreateFrame(
623 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
624 gfx::Size(8, 8), base::TimeDelta())));
625
626 submitter_->DidReceiveFrame();
627 task_environment_.RunUntilIdle();
628 }
629
630 // Test that after context is lost, the CompositorFrameSink is recreated but the
631 // SurfaceEmbedder isn't.
TEST_F(VideoFrameSubmitterTest,RecreateCompositorFrameSinkAfterContextLost)632 TEST_F(VideoFrameSubmitterTest, RecreateCompositorFrameSinkAfterContextLost) {
633 MockEmbeddedFrameSinkProvider mock_embedded_frame_sink_provider;
634 mojo::Receiver<mojom::blink::EmbeddedFrameSinkProvider>
635 embedded_frame_sink_provider_binding(&mock_embedded_frame_sink_provider);
636 auto override =
637 mock_embedded_frame_sink_provider.CreateScopedOverrideMojoInterface(
638 &embedded_frame_sink_provider_binding);
639
640 EXPECT_CALL(*resource_provider_, Initialize(_, _));
641 EXPECT_CALL(mock_embedded_frame_sink_provider, ConnectToEmbedder(_, _))
642 .Times(0);
643 EXPECT_CALL(mock_embedded_frame_sink_provider, CreateCompositorFrameSink_(_))
644 .Times(1);
645 submitter_->OnContextLost();
646 OnReceivedContextProvider(true, context_provider_);
647 task_environment_.RunUntilIdle();
648 }
649
650 // Test that after context is lost, the CompositorFrameSink is recreated but the
651 // SurfaceEmbedder isn't even with software compositing.
TEST_F(VideoFrameSubmitterTest,RecreateCompositorFrameSinkAfterContextLostSoftwareCompositing)652 TEST_F(VideoFrameSubmitterTest,
653 RecreateCompositorFrameSinkAfterContextLostSoftwareCompositing) {
654 MockEmbeddedFrameSinkProvider mock_embedded_frame_sink_provider;
655 mojo::Receiver<mojom::blink::EmbeddedFrameSinkProvider>
656 embedded_frame_sink_provider_binding(&mock_embedded_frame_sink_provider);
657 auto override =
658 mock_embedded_frame_sink_provider.CreateScopedOverrideMojoInterface(
659 &embedded_frame_sink_provider_binding);
660
661 EXPECT_CALL(*resource_provider_, Initialize(_, _));
662 EXPECT_CALL(mock_embedded_frame_sink_provider, ConnectToEmbedder(_, _))
663 .Times(0);
664 EXPECT_CALL(mock_embedded_frame_sink_provider, CreateCompositorFrameSink_(_))
665 .Times(1);
666 submitter_->OnContextLost();
667 OnReceivedContextProvider(false, nullptr);
668 task_environment_.RunUntilIdle();
669 }
670
671 // This test simulates a race condition in which the |video_frame_provider_| is
672 // destroyed before OnReceivedContextProvider returns.
TEST_F(VideoFrameSubmitterTest,StopUsingProviderDuringContextLost)673 TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
674 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
675
676 submitter_->StartRendering();
677 task_environment_.RunUntilIdle();
678
679 EXPECT_SUBMISSION(SubmissionType::kStateChange);
680 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
681 submitter_->StopUsingProvider();
682
683 task_environment_.RunUntilIdle();
684
685 // OnReceivedContextProvider returns. We don't run the actual function
686 // because it would overwrite our fake |sink_| with a real one.
687 SubmitSingleFrame();
688
689 task_environment_.RunUntilIdle();
690 }
691
692 // Test the behaviour of the ChildLocalSurfaceIdAllocator instance. It checks
693 // that the LocalSurfaceId is properly set at creation and updated when the
694 // video frames change.
TEST_F(VideoFrameSubmitterTest,FrameSizeChangeUpdatesLocalSurfaceId)695 TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
696 {
697 viz::LocalSurfaceId local_surface_id =
698 child_local_surface_id_allocator()
699 .GetCurrentLocalSurfaceIdAllocation()
700 .local_surface_id();
701 EXPECT_TRUE(local_surface_id.is_valid());
702 EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
703 EXPECT_EQ(viz::kInitialChildSequenceNumber,
704 local_surface_id.child_sequence_number());
705 EXPECT_TRUE(frame_size().IsEmpty());
706 }
707
708 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
709
710 submitter_->StartRendering();
711 task_environment_.RunUntilIdle();
712
713 EXPECT_SUBMISSION(SubmissionType::kManual);
714 SubmitSingleFrame();
715 task_environment_.RunUntilIdle();
716
717 {
718 viz::LocalSurfaceId local_surface_id =
719 child_local_surface_id_allocator()
720 .GetCurrentLocalSurfaceIdAllocation()
721 .local_surface_id();
722 EXPECT_TRUE(local_surface_id.is_valid());
723 EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
724 EXPECT_EQ(viz::kInitialChildSequenceNumber,
725 local_surface_id.child_sequence_number());
726 EXPECT_EQ(gfx::Size(8, 8), frame_size());
727 AckSubmittedFrame();
728 }
729
730 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
731 .WillOnce(Return(media::VideoFrame::CreateFrame(
732 media::PIXEL_FORMAT_YV12, gfx::Size(2, 2), gfx::Rect(gfx::Size(2, 2)),
733 gfx::Size(2, 2), base::TimeDelta())));
734 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
735 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
736 EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
737 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
738 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
739
740 SubmitSingleFrame();
741 task_environment_.RunUntilIdle();
742
743 {
744 viz::LocalSurfaceId local_surface_id =
745 child_local_surface_id_allocator()
746 .GetCurrentLocalSurfaceIdAllocation()
747 .local_surface_id();
748 EXPECT_TRUE(local_surface_id.is_valid());
749 EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
750 EXPECT_EQ(viz::kInitialChildSequenceNumber + 1,
751 local_surface_id.child_sequence_number());
752 EXPECT_EQ(gfx::Size(2, 2), frame_size());
753 }
754 }
755
TEST_F(VideoFrameSubmitterTest,VideoRotationOutputRect)756 TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
757 MakeSubmitter();
758 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
759 submitter_->StartRendering();
760 EXPECT_TRUE(IsRendering());
761
762 gfx::Size coded_size(1280, 720);
763 gfx::Size natural_size(1280, 1024);
764 gfx::Size rotated_size(1024, 1280);
765
766 {
767 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_90);
768
769 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
770 .WillOnce(Return(true));
771 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
772 .WillOnce(Return(media::VideoFrame::CreateFrame(
773 media::PIXEL_FORMAT_YV12, coded_size, gfx::Rect(coded_size),
774 natural_size, base::TimeDelta())));
775 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
776 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
777 EXPECT_CALL(*resource_provider_,
778 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90, _));
779 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
780 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
781
782 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
783 BEGINFRAME_FROM_HERE, now_src_.get());
784 submitter_->OnBeginFrame(args, {});
785 task_environment_.RunUntilIdle();
786
787 EXPECT_EQ(sink_->last_submitted_compositor_frame().size_in_pixels(),
788 rotated_size);
789
790 AckSubmittedFrame();
791 }
792
793 {
794 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_180);
795
796 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
797 .WillOnce(Return(true));
798 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
799 .WillOnce(Return(media::VideoFrame::CreateFrame(
800 media::PIXEL_FORMAT_YV12, coded_size, gfx::Rect(coded_size),
801 natural_size, base::TimeDelta())));
802 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
803 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
804 EXPECT_CALL(*resource_provider_,
805 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180, _));
806 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
807 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
808
809 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
810 BEGINFRAME_FROM_HERE, now_src_.get());
811 submitter_->OnBeginFrame(args, {});
812 task_environment_.RunUntilIdle();
813
814 // 180 deg rotation has same size.
815 EXPECT_EQ(sink_->last_submitted_compositor_frame().size_in_pixels(),
816 natural_size);
817
818 AckSubmittedFrame();
819 }
820
821 {
822 submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_270);
823
824 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
825 .WillOnce(Return(true));
826 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
827 .WillOnce(Return(media::VideoFrame::CreateFrame(
828 media::PIXEL_FORMAT_YV12, coded_size, gfx::Rect(coded_size),
829 natural_size, base::TimeDelta())));
830 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
831 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
832 EXPECT_CALL(*resource_provider_,
833 AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270, _));
834 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
835 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
836
837 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
838 BEGINFRAME_FROM_HERE, now_src_.get());
839 submitter_->OnBeginFrame(args, {});
840 task_environment_.RunUntilIdle();
841
842 EXPECT_EQ(sink_->last_submitted_compositor_frame().size_in_pixels(),
843 rotated_size);
844
845 AckSubmittedFrame();
846 }
847 }
848
TEST_F(VideoFrameSubmitterTest,PageVisibilityControlsSubmission)849 TEST_F(VideoFrameSubmitterTest, PageVisibilityControlsSubmission) {
850 // Hide the page and ensure no begin frames are issued.
851 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
852 submitter_->SetIsPageVisible(false);
853 task_environment_.RunUntilIdle();
854 EXPECT_FALSE(ShouldSubmit());
855
856 // Start rendering, but since page is hidden nothing should start yet.
857 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
858 submitter_->StartRendering();
859 task_environment_.RunUntilIdle();
860
861 // Mark the page as visible and confirm frame submission.
862 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
863 EXPECT_SUBMISSION(SubmissionType::kStateChange);
864 submitter_->SetIsPageVisible(true);
865 task_environment_.RunUntilIdle();
866
867 // Transition back to the page being hidden and ensure begin frames stop.
868 EXPECT_TRUE(ShouldSubmit());
869 EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
870 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).Times(0);
871 submitter_->SetIsPageVisible(false);
872 task_environment_.RunUntilIdle();
873 }
874
TEST_F(VideoFrameSubmitterTest,PreferredInterval)875 TEST_F(VideoFrameSubmitterTest, PreferredInterval) {
876 video_frame_provider_->preferred_interval = base::TimeDelta::FromSeconds(1);
877
878 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
879
880 submitter_->StartRendering();
881 task_environment_.RunUntilIdle();
882
883 EXPECT_SUBMISSION(SubmissionType::kBeginFrame);
884 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
885 BEGINFRAME_FROM_HERE, now_src_.get());
886 submitter_->OnBeginFrame(args, {});
887 task_environment_.RunUntilIdle();
888
889 EXPECT_EQ(sink_->last_submitted_compositor_frame()
890 .metadata.preferred_frame_interval,
891 video_frame_provider_->preferred_interval);
892 }
893
TEST_F(VideoFrameSubmitterTest,NoDuplicateFramesOnBeginFrame)894 TEST_F(VideoFrameSubmitterTest, NoDuplicateFramesOnBeginFrame) {
895 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
896 submitter_->StartRendering();
897 task_environment_.RunUntilIdle();
898 EXPECT_TRUE(IsRendering());
899
900 auto vf = media::VideoFrame::CreateFrame(
901 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
902 gfx::Size(8, 8), base::TimeDelta());
903
904 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
905 .WillOnce(Return(true));
906 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
907 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
908 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
909 EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
910 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
911 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
912 viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
913 BEGINFRAME_FROM_HERE, now_src_.get());
914 submitter_->OnBeginFrame(args, {});
915 task_environment_.RunUntilIdle();
916 AckSubmittedFrame();
917
918 // Trying to submit the same frame again does nothing... even if
919 // UpdateCurrentFrame() lies about there being a new frame.
920 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
921 .WillOnce(Return(true));
922 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
923 EXPECT_CALL(*sink_, DidNotProduceFrame(_));
924 args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
925 now_src_.get());
926 submitter_->OnBeginFrame(args, {});
927 task_environment_.RunUntilIdle();
928 }
929
TEST_F(VideoFrameSubmitterTest,NoDuplicateFramesDidReceiveFrame)930 TEST_F(VideoFrameSubmitterTest, NoDuplicateFramesDidReceiveFrame) {
931 auto vf = media::VideoFrame::CreateFrame(
932 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
933 gfx::Size(8, 8), base::TimeDelta());
934
935 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
936 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
937 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
938 EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
939 EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
940 EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
941 submitter_->DidReceiveFrame();
942 task_environment_.RunUntilIdle();
943 AckSubmittedFrame();
944
945 // Trying to submit the same frame again does nothing...
946 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
947 submitter_->DidReceiveFrame();
948 task_environment_.RunUntilIdle();
949 }
950
TEST_F(VideoFrameSubmitterTest,ZeroSizedFramesAreNotSubmitted)951 TEST_F(VideoFrameSubmitterTest, ZeroSizedFramesAreNotSubmitted) {
952 auto vf = media::VideoFrame::CreateEOSFrame();
953 ASSERT_TRUE(vf->natural_size().IsEmpty());
954
955 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
956 EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(0);
957 submitter_->DidReceiveFrame();
958 task_environment_.RunUntilIdle();
959 }
960
961 // Check that given enough frames with wallclock duration and enough
962 // presentation feedback data, VideoFrameSubmitter will call the video roughness
963 // reporting callback.
TEST_F(VideoFrameSubmitterTest,ProcessTimingDetails)964 TEST_F(VideoFrameSubmitterTest, ProcessTimingDetails) {
965 int fps = 24;
966 int reports = 0;
967 base::TimeDelta frame_duration = base::TimeDelta::FromSecondsD(1.0 / fps);
968 int frames_to_run =
969 (fps / 2) *
970 (cc::VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit + 1);
971 WTF::HashMap<uint32_t, viz::mojom::blink::FrameTimingDetailsPtr>
972 timing_details;
973
974 MakeSubmitter(
975 base::BindLambdaForTesting([&](int frames, base::TimeDelta duration,
976 double roughness) { reports++; }));
977 EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
978 submitter_->StartRendering();
979 task_environment_.RunUntilIdle();
980 EXPECT_TRUE(IsRendering());
981
982 auto sink_submit = [&](const viz::LocalSurfaceId&,
983 viz::CompositorFrame* frame) {
984 auto token = frame->metadata.frame_token;
985 viz::mojom::blink::FrameTimingDetailsPtr details =
986 viz::mojom::blink::FrameTimingDetails::New();
987 details->presentation_feedback =
988 gfx::mojom::blink::PresentationFeedback::New();
989 details->presentation_feedback->timestamp =
990 base::TimeTicks() + frame_duration * token;
991 timing_details.clear();
992 timing_details.Set(token, std::move(details));
993 };
994
995 EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame)
996 .WillRepeatedly(Return(true));
997 EXPECT_CALL(*video_frame_provider_, PutCurrentFrame).Times(AnyNumber());
998 EXPECT_CALL(*sink_, DoSubmitCompositorFrame)
999 .WillRepeatedly(Invoke(sink_submit));
1000 EXPECT_CALL(*resource_provider_, AppendQuads).Times(AnyNumber());
1001 EXPECT_CALL(*resource_provider_, PrepareSendToParent).Times(AnyNumber());
1002 EXPECT_CALL(*resource_provider_, ReleaseFrameResources).Times(AnyNumber());
1003
1004 for (int i = 0; i < frames_to_run; i++) {
1005 auto frame = media::VideoFrame::CreateFrame(
1006 media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
1007 gfx::Size(8, 8), i * frame_duration);
1008 frame->metadata()->SetTimeDelta(
1009 media::VideoFrameMetadata::WALLCLOCK_FRAME_DURATION, frame_duration);
1010 EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
1011 .WillRepeatedly(Return(frame));
1012
1013 auto args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
1014 now_src_.get());
1015 submitter_->OnBeginFrame(args, std::move(timing_details));
1016 task_environment_.RunUntilIdle();
1017 AckSubmittedFrame();
1018 }
1019 submitter_->StopRendering();
1020 EXPECT_EQ(reports, 1);
1021 }
1022
1023 } // namespace blink
1024