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_(&region, &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