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.
5 #include "media/renderers/video_resource_updater.h"
10 #include "base/functional/bind.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/memory/read_only_shared_memory_region.h"
13 #include "base/test/task_environment.h"
14 #include "components/viz/client/client_resource_provider.h"
15 #include "components/viz/client/shared_bitmap_reporter.h"
16 #include "components/viz/common/quads/compositor_render_pass.h"
17 #include "components/viz/common/quads/texture_draw_quad.h"
18 #include "components/viz/common/resources/shared_image_format.h"
19 #include "components/viz/test/fake_output_surface.h"
20 #include "components/viz/test/test_gles2_interface.h"
21 #include "gpu/GLES2/gl2extchromium.h"
22 #include "gpu/command_buffer/common/mailbox.h"
23 #include "media/base/video_frame.h"
24 #include "skia/ext/skcolorspace_primaries.h"
25 #include "testing/gtest/include/gtest/gtest.h"
30 class FakeSharedBitmapReporter : public viz::SharedBitmapReporter {
32 FakeSharedBitmapReporter() = default;
33 ~FakeSharedBitmapReporter() override = default;
35 // viz::SharedBitmapReporter implementation.
36 void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
37 const viz::SharedBitmapId& id) override {
38 DCHECK_EQ(shared_bitmaps_.count(id), 0u);
39 shared_bitmaps_.insert(id);
41 void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override {
42 DCHECK_EQ(shared_bitmaps_.count(id), 1u);
43 shared_bitmaps_.erase(id);
46 const base::flat_set<viz::SharedBitmapId> shared_bitmaps() const {
47 return shared_bitmaps_;
51 base::flat_set<viz::SharedBitmapId> shared_bitmaps_;
54 class UploadCounterGLES2Interface : public viz::TestGLES2Interface {
56 void TexSubImage2D(GLenum target,
64 const void* pixels) override {
66 last_upload_ = reinterpret_cast<const uint8_t*>(pixels);
69 int UploadCount() { return upload_count_; }
70 void ResetUploadCount() { upload_count_ = 0; }
71 const uint8_t* last_upload() const { return last_upload_; }
75 const uint8_t* last_upload_ = nullptr;
78 class VideoResourceUpdaterTest : public testing::Test {
80 VideoResourceUpdaterTest() {
81 auto gl = std::make_unique<UploadCounterGLES2Interface>();
85 context_provider_ = viz::TestContextProvider::Create(std::move(gl));
86 context_provider_->BindToCurrentSequence();
89 // testing::Test implementation.
90 void SetUp() override {
91 testing::Test::SetUp();
92 resource_provider_ = std::make_unique<viz::ClientResourceProvider>();
95 std::unique_ptr<VideoResourceUpdater> CreateUpdaterForHardware(
96 bool use_stream_video_draw_quad = false) {
97 return std::make_unique<VideoResourceUpdater>(
98 context_provider_.get(), nullptr, resource_provider_.get(),
99 use_stream_video_draw_quad, /*use_gpu_memory_buffer_resources=*/false,
100 /*max_resource_size=*/10000);
103 std::unique_ptr<VideoResourceUpdater> CreateUpdaterForSoftware() {
104 return std::make_unique<VideoResourceUpdater>(
105 /*context_provider=*/nullptr, &shared_bitmap_reporter_,
106 resource_provider_.get(), /*use_stream_video_draw_quad=*/false,
107 /*use_gpu_memory_buffer_resources=*/false, /*max_resource_size=*/10000);
110 // Note that the number of pixels needed for |size| must be less than or equal
111 // to the number of pixels needed for size of 100x100.
112 scoped_refptr<VideoFrame> CreateTestYUVVideoFrame(
113 const gfx::Size& size = gfx::Size(10, 10)) {
114 constexpr int kMaxDimension = 100;
115 static uint8_t y_data[kMaxDimension * kMaxDimension] = {0};
116 static uint8_t u_data[kMaxDimension * kMaxDimension / 2] = {0};
117 static uint8_t v_data[kMaxDimension * kMaxDimension / 2] = {0};
119 CHECK_LE(size.width() * size.height(), kMaxDimension * kMaxDimension);
121 scoped_refptr<VideoFrame> video_frame =
122 VideoFrame::WrapExternalYuvData(PIXEL_FORMAT_I422, // format
124 gfx::Rect(size), // visible_rect
125 size, // natural_size
126 size.width(), // y_stride
127 size.width() / 2, // u_stride
128 size.width() / 2, // v_stride
132 base::TimeDelta()); // timestamp
133 EXPECT_TRUE(video_frame);
137 scoped_refptr<VideoFrame> CreateWonkyTestYUVVideoFrame() {
138 const int kDimension = 10;
139 const int kYWidth = kDimension + 5;
140 const int kUWidth = (kYWidth + 1) / 2 + 200;
141 const int kVWidth = (kYWidth + 1) / 2 + 1;
142 static uint8_t y_data[kYWidth * kDimension] = {0};
143 static uint8_t u_data[kUWidth * kDimension] = {0};
144 static uint8_t v_data[kVWidth * kDimension] = {0};
146 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData(
147 PIXEL_FORMAT_I422, // format
148 gfx::Size(kYWidth, kDimension), // coded_size
149 gfx::Rect(2, 0, kDimension, kDimension), // visible_rect
150 gfx::Size(kDimension, kDimension), // natural_size
151 -kYWidth, // y_stride (negative)
154 y_data + kYWidth * (kDimension - 1), // y_data
157 base::TimeDelta()); // timestamp
158 EXPECT_TRUE(video_frame);
162 scoped_refptr<VideoFrame> CreateTestRGBVideoFrame(VideoPixelFormat format) {
163 constexpr int kMaxDimension = 10;
164 constexpr gfx::Size kSize = gfx::Size(kMaxDimension, kMaxDimension);
165 static uint32_t rgb_data[kMaxDimension * kMaxDimension] = {0};
166 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalData(
169 gfx::Rect(kSize), // visible_rect
170 kSize, // natural_size
171 reinterpret_cast<uint8_t*>(rgb_data), // data,
172 sizeof(rgb_data), // data_size
173 base::TimeDelta()); // timestamp
174 EXPECT_TRUE(video_frame);
178 scoped_refptr<VideoFrame> CreateTestRGBVideoFrameWithVisibleRect(
179 VideoPixelFormat format) {
180 constexpr int kMaxDimension = 5;
181 constexpr gfx::Size kSize = gfx::Size(kMaxDimension, kMaxDimension);
182 constexpr gfx::Rect kVisibleRect = gfx::Rect(2, 1, 3, 3);
183 constexpr uint32_t kPix = 0xFFFFFFFF;
184 static uint32_t rgb_data[kMaxDimension * kMaxDimension] = {
185 0x00, 0x00, 0x00, 0x00, 0x00, //
186 0x00, 0x00, kPix, kPix, kPix, //
187 0x00, 0x00, kPix, kPix, kPix, //
188 0x00, 0x00, kPix, kPix, kPix, //
189 0x00, 0x00, 0x00, 0x00, 0x00, //
192 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalData(
195 kVisibleRect, // visible_rect
196 kVisibleRect.size(), // natural_size
197 reinterpret_cast<uint8_t*>(rgb_data), // data,
198 sizeof(rgb_data), // data_size
199 base::TimeDelta()); // timestamp
200 EXPECT_TRUE(video_frame);
204 scoped_refptr<VideoFrame> CreateTestY16VideoFrameWithVisibleRect() {
205 constexpr int kMaxDimension = 5;
206 constexpr gfx::Size kSize = gfx::Size(kMaxDimension, kMaxDimension);
207 constexpr gfx::Rect kVisibleRect = gfx::Rect(2, 1, 3, 3);
208 constexpr uint16_t kPix = 0xFFFF;
209 static uint16_t y16_data[kMaxDimension * kMaxDimension] = {
210 0x00, 0x00, 0x00, 0x00, 0x00, //
211 0x00, 0x00, kPix, kPix, kPix, //
212 0x00, 0x00, kPix, kPix, kPix, //
213 0x00, 0x00, kPix, kPix, kPix, //
214 0x00, 0x00, 0x00, 0x00, 0x00, //
217 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalData(
220 kVisibleRect, // visible_rect
221 kVisibleRect.size(), // natural_size
222 reinterpret_cast<uint8_t*>(y16_data), // data,
223 sizeof(y16_data), // data_size
224 base::TimeDelta()); // timestamp
225 EXPECT_TRUE(video_frame);
229 scoped_refptr<VideoFrame> CreateTestHighBitFrame() {
230 const int kDimension = 10;
231 gfx::Size size(kDimension, kDimension);
233 scoped_refptr<VideoFrame> video_frame(
234 VideoFrame::CreateFrame(PIXEL_FORMAT_YUV420P10, size, gfx::Rect(size),
235 size, base::TimeDelta()));
236 EXPECT_TRUE(video_frame);
240 scoped_refptr<VideoFrame> CreateNV12TestFrame() {
241 const int kDimension = 10;
242 gfx::Size size(kDimension, kDimension);
244 scoped_refptr<VideoFrame> video_frame(VideoFrame::CreateFrame(
245 PIXEL_FORMAT_NV12, size, gfx::Rect(size), size, base::TimeDelta()));
246 EXPECT_TRUE(video_frame);
250 scoped_refptr<VideoFrame> CreateP016TestFrame() {
251 const int kDimension = 10;
252 gfx::Size size(kDimension, kDimension);
254 scoped_refptr<VideoFrame> video_frame(VideoFrame::CreateFrame(
255 PIXEL_FORMAT_P016LE, size, gfx::Rect(size), size, base::TimeDelta()));
256 EXPECT_TRUE(video_frame);
260 void SetReleaseSyncToken(const gpu::SyncToken& sync_token) {
261 release_sync_token_ = sync_token;
264 scoped_refptr<VideoFrame> CreateTestHardwareVideoFrame(
265 VideoPixelFormat format,
267 const int kDimension = 10;
268 gfx::Size size(kDimension, kDimension);
270 auto mailbox = gpu::Mailbox::GenerateForSharedImage();
272 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes] = {
273 gpu::MailboxHolder(mailbox, kMailboxSyncToken, target)};
274 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativeTextures(
275 format, mailbox_holders,
276 base::BindOnce(&VideoResourceUpdaterTest::SetReleaseSyncToken,
277 base::Unretained(this)),
279 gfx::Rect(size), // visible_rect
280 size, // natural_size
281 base::TimeDelta()); // timestamp
282 EXPECT_TRUE(video_frame);
286 scoped_refptr<VideoFrame> CreateTestRGBAHardwareVideoFrame() {
287 return CreateTestHardwareVideoFrame(PIXEL_FORMAT_ARGB, GL_TEXTURE_2D);
290 scoped_refptr<VideoFrame> CreateTestStreamTextureHardwareVideoFrame(
292 scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame(
293 PIXEL_FORMAT_ARGB, GL_TEXTURE_EXTERNAL_OES);
294 video_frame->metadata().copy_required = needs_copy;
298 #if BUILDFLAG(IS_WIN)
299 scoped_refptr<VideoFrame> CreateTestDCompSurfaceVideoFrame() {
300 scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame(
301 PIXEL_FORMAT_ARGB, GL_TEXTURE_EXTERNAL_OES);
302 video_frame->metadata().dcomp_surface = true;
307 scoped_refptr<VideoFrame> CreateTestYuvHardwareVideoFrame(
308 VideoPixelFormat format,
311 const int kDimension = 10;
312 gfx::Size size(kDimension, kDimension);
314 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
315 for (size_t i = 0; i < num_textures; ++i) {
316 gpu::Mailbox mailbox;
317 mailbox.name[0] = 50 + 1;
319 gpu::MailboxHolder(mailbox, kMailboxSyncToken, target);
321 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativeTextures(
322 format, mailbox_holders,
323 base::BindOnce(&VideoResourceUpdaterTest::SetReleaseSyncToken,
324 base::Unretained(this)),
326 gfx::Rect(size), // visible_rect
327 size, // natural_size
328 base::TimeDelta()); // timestamp
329 EXPECT_TRUE(video_frame);
333 size_t GetSharedImageCount() {
334 return context_provider_->SharedImageInterface()->shared_image_count();
337 static const gpu::SyncToken kMailboxSyncToken;
339 // VideoResourceUpdater registers as a MemoryDumpProvider, which requires
341 base::test::SingleThreadTaskEnvironment task_environment_;
342 raw_ptr<UploadCounterGLES2Interface, DanglingUntriaged> gl_;
343 scoped_refptr<viz::TestContextProvider> context_provider_;
344 FakeSharedBitmapReporter shared_bitmap_reporter_;
345 std::unique_ptr<viz::ClientResourceProvider> resource_provider_;
346 gpu::SyncToken release_sync_token_;
349 const gpu::SyncToken VideoResourceUpdaterTest::kMailboxSyncToken =
350 gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO,
351 gpu::CommandBufferId::FromUnsafeValue(0x123),
354 TEST_F(VideoResourceUpdaterTest, SoftwareFrame) {
355 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
356 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
358 VideoFrameExternalResources resources =
359 updater->CreateExternalResourcesFromVideoFrame(video_frame);
360 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
362 // Setting to kSharedImageFormat, resources type should not change.
363 video_frame->set_shared_image_format_type(
364 SharedImageFormatType::kSharedImageFormat);
365 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
366 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
369 TEST_F(VideoResourceUpdaterTest, SoftwareFrameNV12) {
370 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
372 VideoFrameExternalResources resources =
373 updater->CreateExternalResourcesFromVideoFrame(CreateNV12TestFrame());
374 EXPECT_EQ(VideoFrameResourceType::RGBA, resources.type);
376 // Use a different frame for this test since frames with the same unique_id()
377 // expect to use the same resources.
378 scoped_refptr<VideoFrame> video_frame = CreateNV12TestFrame();
379 gl_->set_supports_texture_rg(true);
380 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
381 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
383 // Setting to kSharedImageFormat, resources type should not change.
384 video_frame->set_shared_image_format_type(
385 SharedImageFormatType::kSharedImageFormat);
386 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
387 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
390 TEST_F(VideoResourceUpdaterTest, SoftwareFrameP016_NoR16Support) {
391 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
393 VideoFrameExternalResources resources =
394 updater->CreateExternalResourcesFromVideoFrame(CreateP016TestFrame());
395 EXPECT_EQ(VideoFrameResourceType::RGBA, resources.type);
398 // Ensure we end up with the right SharedImageFormat for each resource.
399 TEST_F(VideoResourceUpdaterTest, SoftwareFrameRGB) {
400 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
401 for (const auto& fmt : {PIXEL_FORMAT_XBGR, PIXEL_FORMAT_XRGB,
402 PIXEL_FORMAT_ABGR, PIXEL_FORMAT_ARGB}) {
403 scoped_refptr<VideoFrame> video_frame = CreateTestRGBVideoFrame(fmt);
404 VideoFrameExternalResources resources =
405 updater->CreateExternalResourcesFromVideoFrame(video_frame);
406 EXPECT_EQ(VideoFrameResourceType::RGBA, resources.type);
407 #if BUILDFLAG(IS_MAC)
408 EXPECT_EQ(resources.resources[0].format,
409 viz::SinglePlaneFormat::kBGRA_8888);
411 EXPECT_EQ(resources.resources[0].size, video_frame->coded_size());
413 if (fmt == PIXEL_FORMAT_XBGR) {
414 EXPECT_EQ(resources.resources[0].format,
415 viz::SinglePlaneFormat::kRGBA_8888);
416 } else if (fmt == PIXEL_FORMAT_XRGB) {
417 EXPECT_EQ(resources.resources[0].format,
418 viz::SinglePlaneFormat::kBGRA_8888);
420 } else if (fmt == PIXEL_FORMAT_ABGR) {
421 EXPECT_EQ(resources.resources[0].format,
422 viz::SinglePlaneFormat::kRGBA_8888);
424 } else if (fmt == PIXEL_FORMAT_ARGB) {
425 EXPECT_EQ(resources.resources[0].format,
426 viz::SinglePlaneFormat::kBGRA_8888);
432 // Ensure the visible data is where it's supposed to be.
433 TEST_F(VideoResourceUpdaterTest, SoftwareFrameRGBNonOrigin) {
434 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
435 for (const auto& fmt : {PIXEL_FORMAT_XBGR, PIXEL_FORMAT_XRGB,
436 PIXEL_FORMAT_ABGR, PIXEL_FORMAT_ARGB}) {
437 auto video_frame = CreateTestRGBVideoFrameWithVisibleRect(fmt);
438 VideoFrameExternalResources resources =
439 updater->CreateExternalResourcesFromVideoFrame(video_frame);
440 EXPECT_EQ(VideoFrameResourceType::RGBA, resources.type);
441 EXPECT_EQ(resources.resources[0].size, video_frame->coded_size());
443 auto rect = video_frame->visible_rect();
445 const auto bytes_per_row = video_frame->row_bytes(VideoFrame::kARGBPlane);
446 const auto bytes_per_element =
447 VideoFrame::BytesPerElement(fmt, VideoFrame::kARGBPlane);
448 auto* dest_pixels = gl_->last_upload() + rect.y() * bytes_per_row +
449 rect.x() * bytes_per_element;
450 auto* src_pixels = video_frame->visible_data(VideoFrame::kARGBPlane);
452 // Pixels are 0xFFFFFFFF, so channel reordering doesn't matter.
453 for (int y = 0; y < rect.height(); ++y) {
454 for (int x = 0; x < rect.width() * bytes_per_element; ++x) {
455 const auto pos = y * bytes_per_row + x;
456 ASSERT_EQ(src_pixels[pos], dest_pixels[pos]);
462 // Ensure the visible data is where it's supposed to be.
463 TEST_F(VideoResourceUpdaterTest, SoftwareFrameY16NonOrigin) {
464 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
466 auto video_frame = CreateTestY16VideoFrameWithVisibleRect();
467 VideoFrameExternalResources resources =
468 updater->CreateExternalResourcesFromVideoFrame(video_frame);
469 EXPECT_EQ(VideoFrameResourceType::RGBA, resources.type);
470 EXPECT_EQ(resources.resources[0].size, video_frame->coded_size());
472 auto rect = video_frame->visible_rect();
474 // Just used for sizing information, channel order doesn't matter.
475 constexpr auto kOutputFormat = PIXEL_FORMAT_ARGB;
477 const auto bytes_per_row = VideoFrame::RowBytes(
478 VideoFrame::kARGBPlane, kOutputFormat, video_frame->coded_size().width());
479 const auto bytes_per_element =
480 VideoFrame::BytesPerElement(kOutputFormat, VideoFrame::kARGBPlane);
481 auto* dest_pixels = gl_->last_upload() + rect.y() * bytes_per_row +
482 rect.x() * bytes_per_element;
484 // Pixels are 0xFFFFFFFF, so channel reordering doesn't matter.
485 for (int y = 0; y < rect.height(); ++y) {
486 for (int x = 0; x < rect.width() * bytes_per_element; ++x) {
487 const auto pos = y * bytes_per_row + x;
488 ASSERT_EQ(0xFF, dest_pixels[pos]);
493 TEST_F(VideoResourceUpdaterTest, HighBitFrameNoF16) {
494 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
495 scoped_refptr<VideoFrame> video_frame = CreateTestHighBitFrame();
497 VideoFrameExternalResources resources =
498 updater->CreateExternalResourcesFromVideoFrame(video_frame);
499 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
501 // Setting to kSharedImageFormat, resources type should not change.
502 video_frame->set_shared_image_format_type(
503 SharedImageFormatType::kSharedImageFormat);
504 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
505 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
508 class VideoResourceUpdaterTestWithF16 : public VideoResourceUpdaterTest {
510 VideoResourceUpdaterTestWithF16() : VideoResourceUpdaterTest() {
511 gl_->set_support_texture_half_float_linear(true);
515 TEST_F(VideoResourceUpdaterTestWithF16, HighBitFrame) {
516 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
517 scoped_refptr<VideoFrame> video_frame = CreateTestHighBitFrame();
519 VideoFrameExternalResources resources =
520 updater->CreateExternalResourcesFromVideoFrame(video_frame);
521 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
522 EXPECT_NEAR(resources.multiplier, 2.0, 0.1);
523 EXPECT_NEAR(resources.offset, 0.5, 0.1);
525 // Create the resource again, to test the path where the
526 // resources are cached.
527 VideoFrameExternalResources resources2 =
528 updater->CreateExternalResourcesFromVideoFrame(video_frame);
529 EXPECT_EQ(VideoFrameResourceType::YUV, resources2.type);
530 EXPECT_NEAR(resources2.multiplier, 2.0, 0.1);
531 EXPECT_NEAR(resources2.offset, 0.5, 0.1);
534 class VideoResourceUpdaterTestWithR16 : public VideoResourceUpdaterTest {
536 VideoResourceUpdaterTestWithR16() : VideoResourceUpdaterTest() {
537 auto* sii = context_provider_->SharedImageInterface();
538 auto shared_image_caps = sii->GetCapabilities();
539 shared_image_caps.supports_r16_shared_images = true;
540 sii->SetCapabilities(shared_image_caps);
542 gl_->set_support_texture_norm16(true);
546 TEST_F(VideoResourceUpdaterTestWithR16, SoftwareFrameP016) {
547 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
549 VideoFrameExternalResources resources =
550 updater->CreateExternalResourcesFromVideoFrame(CreateP016TestFrame());
551 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
554 TEST_F(VideoResourceUpdaterTestWithR16, HighBitFrame) {
555 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
556 scoped_refptr<VideoFrame> video_frame = CreateTestHighBitFrame();
558 VideoFrameExternalResources resources =
559 updater->CreateExternalResourcesFromVideoFrame(video_frame);
560 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
562 // Max 10-bit values as read by a sampler.
563 double max_10bit_value = ((1 << 10) - 1) / 65535.0;
564 EXPECT_NEAR(resources.multiplier * max_10bit_value, 1.0, 0.0001);
565 EXPECT_NEAR(resources.offset, 0.0, 0.1);
567 // Create the resource again, to test the path where the
568 // resources are cached.
569 VideoFrameExternalResources resources2 =
570 updater->CreateExternalResourcesFromVideoFrame(video_frame);
571 EXPECT_EQ(VideoFrameResourceType::YUV, resources2.type);
572 EXPECT_NEAR(resources2.multiplier * max_10bit_value, 1.0, 0.0001);
573 EXPECT_NEAR(resources2.offset, 0.0, 0.1);
576 TEST_F(VideoResourceUpdaterTest, NV12FrameSoftwareCompositor) {
577 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
578 scoped_refptr<VideoFrame> video_frame = CreateNV12TestFrame();
580 VideoFrameExternalResources resources =
581 updater->CreateExternalResourcesFromVideoFrame(video_frame);
582 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
585 TEST_F(VideoResourceUpdaterTest, P016FrameSoftwareCompositor) {
586 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
587 scoped_refptr<VideoFrame> video_frame = CreateP016TestFrame();
589 VideoFrameExternalResources resources =
590 updater->CreateExternalResourcesFromVideoFrame(video_frame);
591 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
594 TEST_F(VideoResourceUpdaterTest, HighBitFrameSoftwareCompositor) {
595 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
596 scoped_refptr<VideoFrame> video_frame = CreateTestHighBitFrame();
598 VideoFrameExternalResources resources =
599 updater->CreateExternalResourcesFromVideoFrame(video_frame);
600 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
603 TEST_F(VideoResourceUpdaterTest, WonkySoftwareFrame) {
604 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
605 scoped_refptr<VideoFrame> video_frame = CreateWonkyTestYUVVideoFrame();
607 VideoFrameExternalResources resources =
608 updater->CreateExternalResourcesFromVideoFrame(video_frame);
609 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
611 // Setting to kSharedImageFormat, resources type should not change.
612 video_frame->set_shared_image_format_type(
613 SharedImageFormatType::kSharedImageFormat);
614 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
615 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
618 TEST_F(VideoResourceUpdaterTest, WonkySoftwareFrameSoftwareCompositor) {
619 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
620 scoped_refptr<VideoFrame> video_frame = CreateWonkyTestYUVVideoFrame();
622 VideoFrameExternalResources resources =
623 updater->CreateExternalResourcesFromVideoFrame(video_frame);
624 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
627 TEST_F(VideoResourceUpdaterTest, ReuseResource) {
628 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
629 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
630 video_frame->set_timestamp(base::Seconds(1234));
632 // Allocate the resources for a YUV video frame.
633 gl_->ResetUploadCount();
634 VideoFrameExternalResources resources =
635 updater->CreateExternalResourcesFromVideoFrame(video_frame);
636 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
637 EXPECT_EQ(3u, resources.resources.size());
638 EXPECT_EQ(3u, resources.release_callbacks.size());
639 // Expect exactly three texture uploads, one for each plane.
640 EXPECT_EQ(3, gl_->UploadCount());
642 // Simulate the ResourceProvider releasing the resources back to the video
644 for (auto& release_callback : resources.release_callbacks)
645 std::move(release_callback).Run(gpu::SyncToken(), false);
647 // Allocate resources for the same frame.
648 gl_->ResetUploadCount();
649 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
650 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
651 EXPECT_EQ(3u, resources.resources.size());
652 EXPECT_EQ(3u, resources.release_callbacks.size());
653 // The data should be reused so expect no texture uploads.
654 EXPECT_EQ(0, gl_->UploadCount());
657 TEST_F(VideoResourceUpdaterTest, ReuseResourceNV12) {
658 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
659 scoped_refptr<VideoFrame> video_frame = CreateNV12TestFrame();
660 video_frame->set_timestamp(base::Seconds(1234));
661 gl_->set_supports_texture_rg(true);
663 // Allocate the resources for a YUV video frame.
664 gl_->ResetUploadCount();
665 VideoFrameExternalResources resources =
666 updater->CreateExternalResourcesFromVideoFrame(video_frame);
667 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
668 EXPECT_EQ(2u, resources.resources.size());
669 EXPECT_EQ(2u, resources.release_callbacks.size());
670 // Expect exactly three texture uploads, one for each plane.
671 EXPECT_EQ(2, gl_->UploadCount());
673 // Simulate the ResourceProvider releasing the resources back to the video
675 for (auto& release_callback : resources.release_callbacks)
676 std::move(release_callback).Run(gpu::SyncToken(), false);
678 // Allocate resources for the same frame.
679 gl_->ResetUploadCount();
680 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
681 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
682 EXPECT_EQ(2u, resources.resources.size());
683 EXPECT_EQ(2u, resources.release_callbacks.size());
684 // The data should be reused so expect no texture uploads.
685 EXPECT_EQ(0, gl_->UploadCount());
688 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) {
689 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
690 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
691 video_frame->set_timestamp(base::Seconds(1234));
693 // Allocate the resources for a YUV video frame.
694 gl_->ResetUploadCount();
695 VideoFrameExternalResources resources =
696 updater->CreateExternalResourcesFromVideoFrame(video_frame);
697 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
698 EXPECT_EQ(3u, resources.resources.size());
699 EXPECT_EQ(3u, resources.release_callbacks.size());
700 // Expect exactly three texture uploads, one for each plane.
701 EXPECT_EQ(3, gl_->UploadCount());
703 // Allocate resources for the same frame.
704 gl_->ResetUploadCount();
705 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
706 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
707 EXPECT_EQ(3u, resources.resources.size());
708 EXPECT_EQ(3u, resources.release_callbacks.size());
709 // The data should be reused so expect no texture uploads.
710 EXPECT_EQ(0, gl_->UploadCount());
713 TEST_F(VideoResourceUpdaterTest, SoftwareFrameSoftwareCompositor) {
714 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
715 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
717 VideoFrameExternalResources resources =
718 updater->CreateExternalResourcesFromVideoFrame(video_frame);
719 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
722 TEST_F(VideoResourceUpdaterTest, SoftwareFrameRGBSoftwareCompositor) {
723 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
724 for (const auto& fmt : {PIXEL_FORMAT_XBGR, PIXEL_FORMAT_XRGB,
725 PIXEL_FORMAT_ABGR, PIXEL_FORMAT_ARGB}) {
726 scoped_refptr<VideoFrame> video_frame = CreateTestRGBVideoFrame(fmt);
727 VideoFrameExternalResources resources =
728 updater->CreateExternalResourcesFromVideoFrame(video_frame);
729 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
730 EXPECT_EQ(resources.resources[0].format,
731 viz::SinglePlaneFormat::kRGBA_8888);
735 TEST_F(VideoResourceUpdaterTest, ReuseResourceSoftwareCompositor) {
736 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
737 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
738 video_frame->set_timestamp(base::Seconds(1234));
740 // Allocate the resources for a software video frame.
741 VideoFrameExternalResources resources =
742 updater->CreateExternalResourcesFromVideoFrame(video_frame);
743 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
744 EXPECT_EQ(1u, resources.resources.size());
745 EXPECT_EQ(1u, resources.release_callbacks.size());
746 // Expect exactly one allocated shared bitmap.
747 EXPECT_EQ(1u, shared_bitmap_reporter_.shared_bitmaps().size());
748 auto shared_bitmaps_copy = shared_bitmap_reporter_.shared_bitmaps();
750 // Simulate the ResourceProvider releasing the resource back to the video
752 std::move(resources.release_callbacks[0]).Run(gpu::SyncToken(), false);
754 // Allocate resources for the same frame.
755 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
756 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
757 EXPECT_EQ(1u, resources.resources.size());
758 EXPECT_EQ(1u, resources.release_callbacks.size());
760 // Ensure that the same shared bitmap was reused.
761 EXPECT_EQ(shared_bitmap_reporter_.shared_bitmaps(), shared_bitmaps_copy);
764 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDeleteSoftwareCompositor) {
765 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
766 scoped_refptr<VideoFrame> video_frame = CreateTestYUVVideoFrame();
767 video_frame->set_timestamp(base::Seconds(1234));
769 // Allocate the resources for a software video frame.
770 VideoFrameExternalResources resources =
771 updater->CreateExternalResourcesFromVideoFrame(video_frame);
772 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
773 EXPECT_EQ(1u, resources.resources.size());
774 EXPECT_EQ(1u, resources.release_callbacks.size());
775 // Expect exactly one allocated shared bitmap.
776 EXPECT_EQ(1u, shared_bitmap_reporter_.shared_bitmaps().size());
777 auto shared_bitmaps_copy = shared_bitmap_reporter_.shared_bitmaps();
779 // Allocate resources for the same frame.
780 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
781 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
782 EXPECT_EQ(1u, resources.resources.size());
783 EXPECT_EQ(1u, resources.release_callbacks.size());
785 // Ensure that the same shared bitmap was reused.
786 EXPECT_EQ(shared_bitmap_reporter_.shared_bitmaps(), shared_bitmaps_copy);
789 TEST_F(VideoResourceUpdaterTest, ChangeResourceSizeSoftwareCompositor) {
790 constexpr gfx::Size kSize1(10, 10);
791 constexpr gfx::Size kSize2(20, 20);
793 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForSoftware();
795 // Allocate the resources for a software video frame.
796 VideoFrameExternalResources resources =
797 updater->CreateExternalResourcesFromVideoFrame(
798 CreateTestYUVVideoFrame(kSize1));
799 // Expect exactly one allocated shared bitmap.
800 EXPECT_EQ(1u, shared_bitmap_reporter_.shared_bitmaps().size());
801 auto shared_bitmaps_copy = shared_bitmap_reporter_.shared_bitmaps();
803 // Simulate the ResourceProvider releasing the resource back to the video
805 std::move(resources.release_callbacks[0]).Run(gpu::SyncToken(), false);
807 // Allocate resources for the next frame with a different size.
808 resources = updater->CreateExternalResourcesFromVideoFrame(
809 CreateTestYUVVideoFrame(kSize2));
811 // The first resource was released, so it can be reused but it's the wrong
812 // size. We should expect the first shared bitmap to be deleted and a new
813 // shared bitmap to be allocated.
814 EXPECT_EQ(1u, shared_bitmap_reporter_.shared_bitmaps().size());
815 EXPECT_NE(shared_bitmap_reporter_.shared_bitmaps(), shared_bitmaps_copy);
818 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_ResourceFormat) {
819 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
821 scoped_refptr<VideoFrame> video_frame = CreateTestRGBAHardwareVideoFrame();
823 VideoFrameExternalResources resources =
824 updater->CreateExternalResourcesFromVideoFrame(video_frame);
825 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
826 EXPECT_EQ(1u, resources.resources.size());
827 EXPECT_EQ(1u, resources.release_callbacks.size());
829 video_frame = CreateTestYuvHardwareVideoFrame(PIXEL_FORMAT_I420, 3,
830 GL_TEXTURE_RECTANGLE_ARB);
832 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
833 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
834 EXPECT_EQ(3u, resources.resources.size());
835 EXPECT_EQ(3u, resources.release_callbacks.size());
836 EXPECT_EQ(viz::SinglePlaneFormat::kR_8, resources.resources[0].format);
837 EXPECT_EQ(viz::SinglePlaneFormat::kR_8, resources.resources[1].format);
838 EXPECT_EQ(viz::SinglePlaneFormat::kR_8, resources.resources[2].format);
839 EXPECT_EQ(resources.resources[0].synchronization_type,
840 viz::TransferableResource::SynchronizationType::kSyncToken);
841 EXPECT_EQ(resources.resources[1].synchronization_type,
842 viz::TransferableResource::SynchronizationType::kSyncToken);
843 EXPECT_EQ(resources.resources[2].synchronization_type,
844 viz::TransferableResource::SynchronizationType::kSyncToken);
846 video_frame = CreateTestYuvHardwareVideoFrame(PIXEL_FORMAT_I420, 3,
847 GL_TEXTURE_RECTANGLE_ARB);
848 video_frame->metadata().read_lock_fences_enabled = true;
850 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
852 resources.resources[0].synchronization_type,
853 viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted);
855 resources.resources[1].synchronization_type,
856 viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted);
858 resources.resources[2].synchronization_type,
859 viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted);
862 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SharedImageFormat) {
863 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
864 scoped_refptr<VideoFrame> video_frame = CreateTestYuvHardwareVideoFrame(
865 PIXEL_FORMAT_I420, 1, GL_TEXTURE_RECTANGLE_ARB);
866 // Setting to kSharedImageFormat, resources type should change to RGB.
867 video_frame->set_shared_image_format_type(
868 SharedImageFormatType::kSharedImageFormat);
869 VideoFrameExternalResources resources =
870 updater->CreateExternalResourcesFromVideoFrame(video_frame);
871 EXPECT_EQ(VideoFrameResourceType::RGB, resources.type);
872 EXPECT_EQ(1u, resources.resources.size());
873 EXPECT_EQ(1u, resources.release_callbacks.size());
874 EXPECT_EQ(viz::MultiPlaneFormat::kI420, resources.resources[0].format);
875 EXPECT_EQ(resources.resources[0].synchronization_type,
876 viz::TransferableResource::SynchronizationType::kSyncToken);
878 video_frame = CreateTestYuvHardwareVideoFrame(PIXEL_FORMAT_I420, 1,
879 GL_TEXTURE_RECTANGLE_ARB);
880 video_frame->set_shared_image_format_type(
881 SharedImageFormatType::kSharedImageFormat);
882 video_frame->metadata().read_lock_fences_enabled = true;
884 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
886 resources.resources[0].synchronization_type,
887 viz::TransferableResource::SynchronizationType::kGpuCommandsCompleted);
890 TEST_F(VideoResourceUpdaterTest,
891 CreateForHardwarePlanes_StreamTexture_CopyToNewTexture) {
892 // Note that |use_stream_video_draw_quad| is true for this test.
893 std::unique_ptr<VideoResourceUpdater> updater =
894 CreateUpdaterForHardware(true);
895 EXPECT_EQ(0u, GetSharedImageCount());
896 scoped_refptr<VideoFrame> video_frame =
897 CreateTestStreamTextureHardwareVideoFrame(/*needs_copy=*/false);
899 VideoFrameExternalResources resources =
900 updater->CreateExternalResourcesFromVideoFrame(video_frame);
901 EXPECT_EQ(VideoFrameResourceType::STREAM_TEXTURE, resources.type);
902 EXPECT_EQ(1u, resources.resources.size());
903 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
904 resources.resources[0].mailbox_holder.texture_target);
905 EXPECT_EQ(1u, resources.release_callbacks.size());
906 EXPECT_EQ(0u, GetSharedImageCount());
908 // A copied stream texture should return an RGBA resource in a new
909 // GL_TEXTURE_2D texture.
910 video_frame = CreateTestStreamTextureHardwareVideoFrame(/*needs_copy=*/true);
911 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
912 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
913 EXPECT_EQ(1u, resources.resources.size());
914 EXPECT_EQ((GLenum)GL_TEXTURE_2D,
915 resources.resources[0].mailbox_holder.texture_target);
916 EXPECT_EQ(1u, resources.release_callbacks.size());
917 EXPECT_EQ(1u, GetSharedImageCount());
920 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_TextureQuad) {
921 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
922 EXPECT_EQ(0u, GetSharedImageCount());
923 scoped_refptr<VideoFrame> video_frame =
924 CreateTestStreamTextureHardwareVideoFrame(/*needs_copy=*/false);
926 VideoFrameExternalResources resources =
927 updater->CreateExternalResourcesFromVideoFrame(video_frame);
928 EXPECT_EQ(VideoFrameResourceType::RGBA_PREMULTIPLIED, resources.type);
929 EXPECT_EQ(1u, resources.resources.size());
930 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
931 resources.resources[0].mailbox_holder.texture_target);
932 EXPECT_EQ(1u, resources.release_callbacks.size());
933 EXPECT_EQ(0u, GetSharedImageCount());
936 #if BUILDFLAG(IS_WIN)
937 // Check that a video frame marked as containing a DComp surface turns into a
938 // texture draw quad that is required for overlay.
939 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_DCompSurface) {
940 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
941 EXPECT_EQ(0u, GetSharedImageCount());
942 scoped_refptr<VideoFrame> video_frame = CreateTestDCompSurfaceVideoFrame();
944 VideoFrameExternalResources resources =
945 updater->CreateExternalResourcesFromVideoFrame(video_frame);
946 EXPECT_EQ(VideoFrameResourceType::STREAM_TEXTURE, resources.type);
947 EXPECT_EQ(1u, resources.resources.size());
948 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
949 resources.resources[0].mailbox_holder.texture_target);
950 EXPECT_EQ(1u, resources.release_callbacks.size());
951 EXPECT_EQ(0u, GetSharedImageCount());
953 updater->ObtainFrameResources(video_frame);
955 std::unique_ptr<viz::CompositorRenderPass> pass =
956 viz::CompositorRenderPass::Create();
957 pass->SetNew(/*pass_id=*/viz::CompositorRenderPassId{1},
958 /*output_rect=*/gfx::Rect(video_frame->coded_size()),
959 /*damage_rect=*/gfx::Rect(),
960 /*transform_to_root_target=*/gfx::Transform());
961 updater->AppendQuads(
962 /*render_pass=*/pass.get(), video_frame,
963 /*transform=*/gfx::Transform(),
964 /*quad_rect=*/gfx::Rect(video_frame->coded_size()),
965 /*visible_quad_rect=*/gfx::Rect(video_frame->coded_size()),
966 gfx::MaskFilterInfo(), /*clip_rect=*/absl::nullopt,
967 /*context_opaque=*/true, /*draw_opacity=*/1.0,
968 /*sorting_context_id=*/0);
970 EXPECT_EQ(1u, pass->quad_list.size());
972 const viz::TextureDrawQuad* quad =
973 pass->quad_list.ElementAt(0)->DynamicCast<viz::TextureDrawQuad>();
974 EXPECT_NE(nullptr, quad);
975 EXPECT_EQ(true, quad->is_stream_video);
976 EXPECT_EQ(viz::OverlayPriority::kRequired, quad->overlay_priority_hint);
978 updater->ReleaseFrameResources();
982 // Passthrough the sync token returned by the compositor if we don't have an
983 // existing release sync token.
984 TEST_F(VideoResourceUpdaterTest, PassReleaseSyncToken) {
985 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
987 const gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
988 gpu::CommandBufferId::FromUnsafeValue(0x123),
992 scoped_refptr<VideoFrame> video_frame = CreateTestRGBAHardwareVideoFrame();
994 VideoFrameExternalResources resources =
995 updater->CreateExternalResourcesFromVideoFrame(video_frame);
997 ASSERT_EQ(resources.release_callbacks.size(), 1u);
998 std::move(resources.release_callbacks[0]).Run(sync_token, false);
1001 EXPECT_EQ(release_sync_token_, sync_token);
1004 // Generate new sync token because video frame has an existing sync token.
1005 TEST_F(VideoResourceUpdaterTest, GenerateReleaseSyncToken) {
1006 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1008 const gpu::SyncToken sync_token1(gpu::CommandBufferNamespace::GPU_IO,
1009 gpu::CommandBufferId::FromUnsafeValue(0x123),
1012 const gpu::SyncToken sync_token2(gpu::CommandBufferNamespace::GPU_IO,
1013 gpu::CommandBufferId::FromUnsafeValue(0x234),
1017 scoped_refptr<VideoFrame> video_frame = CreateTestRGBAHardwareVideoFrame();
1019 VideoFrameExternalResources resources1 =
1020 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1021 ASSERT_EQ(resources1.release_callbacks.size(), 1u);
1022 std::move(resources1.release_callbacks[0]).Run(sync_token1, false);
1024 VideoFrameExternalResources resources2 =
1025 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1026 ASSERT_EQ(resources2.release_callbacks.size(), 1u);
1027 std::move(resources2.release_callbacks[0]).Run(sync_token2, false);
1030 EXPECT_TRUE(release_sync_token_.HasData());
1031 EXPECT_NE(release_sync_token_, sync_token1);
1032 EXPECT_EQ(release_sync_token_, sync_token2);
1035 // Pass mailbox sync token as is if no GL operations are performed before frame
1036 // resources are handed off to the compositor.
1037 TEST_F(VideoResourceUpdaterTest, PassMailboxSyncToken) {
1038 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1040 scoped_refptr<VideoFrame> video_frame = CreateTestRGBAHardwareVideoFrame();
1042 VideoFrameExternalResources resources =
1043 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1045 ASSERT_EQ(resources.resources.size(), 1u);
1046 EXPECT_TRUE(resources.resources[0].mailbox_holder.sync_token.HasData());
1047 EXPECT_EQ(resources.resources[0].mailbox_holder.sync_token,
1051 // Generate new sync token for compositor when copying the texture.
1052 TEST_F(VideoResourceUpdaterTest, GenerateSyncTokenOnTextureCopy) {
1053 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1055 scoped_refptr<VideoFrame> video_frame =
1056 CreateTestStreamTextureHardwareVideoFrame(/*needs_copy=*/true);
1058 VideoFrameExternalResources resources =
1059 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1061 ASSERT_EQ(resources.resources.size(), 1u);
1062 EXPECT_TRUE(resources.resources[0].mailbox_holder.sync_token.HasData());
1063 EXPECT_NE(resources.resources[0].mailbox_holder.sync_token,
1067 // NV12 VideoFrames backed by a single native texture can be sampled out
1068 // by GL as RGB. To use them as HW overlays we need to know the format
1069 // of the underlying buffer, that is YUV_420_BIPLANAR.
1070 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleNV12) {
1071 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1072 EXPECT_EQ(0u, GetSharedImageCount());
1073 scoped_refptr<VideoFrame> video_frame =
1074 CreateTestHardwareVideoFrame(PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES);
1076 VideoFrameExternalResources resources =
1077 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1078 EXPECT_EQ(VideoFrameResourceType::RGB, resources.type);
1079 EXPECT_EQ(1u, resources.resources.size());
1080 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
1081 resources.resources[0].mailbox_holder.texture_target);
1082 EXPECT_EQ(viz::LegacyMultiPlaneFormat::kNV12, resources.resources[0].format);
1083 EXPECT_EQ(0u, GetSharedImageCount());
1086 TEST_F(VideoResourceUpdaterTest,
1087 CreateForHardwarePlanes_DualNV12_ResourceFormat) {
1088 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1089 EXPECT_EQ(0u, GetSharedImageCount());
1090 scoped_refptr<VideoFrame> video_frame = CreateTestYuvHardwareVideoFrame(
1091 PIXEL_FORMAT_NV12, 2, GL_TEXTURE_EXTERNAL_OES);
1093 VideoFrameExternalResources resources =
1094 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1095 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
1096 EXPECT_EQ(2u, resources.resources.size());
1097 EXPECT_EQ(2u, resources.release_callbacks.size());
1098 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
1099 resources.resources[0].mailbox_holder.texture_target);
1100 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
1101 resources.resources[1].mailbox_holder.texture_target);
1102 // |updater| doesn't set |buffer_format| in this case.
1103 EXPECT_EQ(viz::SinglePlaneFormat::kR_8, resources.resources[0].format);
1104 EXPECT_EQ(viz::SinglePlaneFormat::kRG_88, resources.resources[1].format);
1106 video_frame = CreateTestYuvHardwareVideoFrame(PIXEL_FORMAT_NV12, 2,
1107 GL_TEXTURE_RECTANGLE_ARB);
1108 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
1109 EXPECT_EQ(VideoFrameResourceType::YUV, resources.type);
1110 EXPECT_EQ(2u, resources.resources.size());
1111 EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB,
1112 resources.resources[0].mailbox_holder.texture_target);
1113 EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB,
1114 resources.resources[1].mailbox_holder.texture_target);
1115 EXPECT_EQ(viz::SinglePlaneFormat::kR_8, resources.resources[0].format);
1116 EXPECT_EQ(viz::SinglePlaneFormat::kRG_88, resources.resources[1].format);
1117 EXPECT_EQ(0u, GetSharedImageCount());
1120 TEST_F(VideoResourceUpdaterTest,
1121 CreateForHardwarePlanes_DualNV12_SharedImageFormat) {
1122 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1123 EXPECT_EQ(0u, GetSharedImageCount());
1124 scoped_refptr<VideoFrame> video_frame = CreateTestYuvHardwareVideoFrame(
1125 PIXEL_FORMAT_NV12, 1, GL_TEXTURE_RECTANGLE_ARB);
1126 video_frame->set_shared_image_format_type(
1127 SharedImageFormatType::kSharedImageFormat);
1128 VideoFrameExternalResources resources =
1129 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1130 // Setting to kSharedImageFormat, resources type should bo RGB.
1131 EXPECT_EQ(VideoFrameResourceType::RGB, resources.type);
1132 EXPECT_EQ(1u, resources.resources.size());
1133 EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB,
1134 resources.resources[0].mailbox_holder.texture_target);
1135 EXPECT_EQ(viz::MultiPlaneFormat::kNV12, resources.resources[0].format);
1136 EXPECT_EQ(0u, GetSharedImageCount());
1138 video_frame = CreateTestYuvHardwareVideoFrame(PIXEL_FORMAT_NV12, 1,
1139 GL_TEXTURE_EXTERNAL_OES);
1140 video_frame->set_shared_image_format_type(
1141 SharedImageFormatType::kSharedImageFormat);
1143 resources = updater->CreateExternalResourcesFromVideoFrame(video_frame);
1144 EXPECT_EQ(VideoFrameResourceType::RGB, resources.type);
1145 EXPECT_EQ(1u, resources.resources.size());
1146 EXPECT_EQ(1u, resources.release_callbacks.size());
1147 EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
1148 resources.resources[0].mailbox_holder.texture_target);
1149 // |updater| doesn't set |buffer_format| in this case.
1150 EXPECT_EQ(viz::MultiPlaneFormat::kNV12, resources.resources[0].format);
1151 EXPECT_EQ(0u, GetSharedImageCount());
1154 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleP016HDR) {
1155 constexpr auto kHDR10ColorSpace = gfx::ColorSpace::CreateHDR10();
1156 gfx::HDRMetadata hdr_metadata{};
1157 hdr_metadata.smpte_st_2086 =
1158 gfx::HdrMetadataSmpteSt2086(SkNamedPrimariesExt::kP3,
1159 /*luminance_max=*/1000,
1160 /*luminance_min=*/0);
1161 std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware();
1162 EXPECT_EQ(0u, GetSharedImageCount());
1163 scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame(
1164 PIXEL_FORMAT_P016LE, GL_TEXTURE_EXTERNAL_OES);
1165 video_frame->set_color_space(kHDR10ColorSpace);
1166 video_frame->set_hdr_metadata(hdr_metadata);
1168 VideoFrameExternalResources resources =
1169 updater->CreateExternalResourcesFromVideoFrame(video_frame);
1170 EXPECT_EQ(VideoFrameResourceType::RGB, resources.type);
1171 EXPECT_EQ(1u, resources.resources.size());
1172 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
1173 resources.resources[0].mailbox_holder.texture_target);
1174 EXPECT_EQ(viz::LegacyMultiPlaneFormat::kP010, resources.resources[0].format);
1175 EXPECT_EQ(kHDR10ColorSpace, resources.resources[0].color_space);
1176 EXPECT_EQ(hdr_metadata, resources.resources[0].hdr_metadata);
1177 EXPECT_EQ(0u, GetSharedImageCount());
1181 } // namespace media