1 // Copyright 2021 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/shared_image_video_frame_test_utils.h"
7 #include "base/logging.h"
8 #include "components/viz/common/gpu/context_provider.h"
9 #include "components/viz/common/resources/shared_image_format.h"
10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "gpu/command_buffer/client/client_shared_image.h"
12 #include "gpu/command_buffer/client/gles2_interface_stub.h"
13 #include "gpu/command_buffer/client/shared_image_interface.h"
14 #include "gpu/command_buffer/common/capabilities.h"
15 #include "gpu/command_buffer/common/shared_image_usage.h"
21 static constexpr const uint8_t kYuvColors[8][3] = {
22 {0x00, 0x80, 0x80}, // Black
23 {0x4c, 0x54, 0xff}, // Red
24 {0x95, 0x2b, 0x15}, // Green
25 {0xe1, 0x00, 0x94}, // Yellow
26 {0x1d, 0xff, 0x6b}, // Blue
27 {0x69, 0xd3, 0xec}, // Magenta
28 {0xb3, 0xaa, 0x00}, // Cyan
29 {0xff, 0x80, 0x80}, // White
32 // Destroys a list of shared images after a sync token is passed. Also runs
34 void DestroySharedImages(scoped_refptr<viz::ContextProvider> context_provider,
35 std::vector<gpu::Mailbox> mailboxes,
36 base::OnceClosure callback,
37 const gpu::SyncToken& sync_token) {
38 auto* sii = context_provider->SharedImageInterface();
39 for (const auto& mailbox : mailboxes)
40 sii->DestroySharedImage(sync_token, mailbox);
41 std::move(callback).Run();
46 scoped_refptr<VideoFrame> CreateSharedImageFrame(
47 scoped_refptr<viz::ContextProvider> context_provider,
48 VideoPixelFormat format,
49 std::vector<gpu::Mailbox> mailboxes,
50 const gpu::SyncToken& sync_token,
51 GLenum texture_target,
52 const gfx::Size& coded_size,
53 const gfx::Rect& visible_rect,
54 const gfx::Size& natural_size,
55 base::TimeDelta timestamp,
56 base::OnceClosure destroyed_callback) {
57 gpu::MailboxHolder mailboxes_for_frame[VideoFrame::kMaxPlanes] = {};
59 for (const auto& mailbox : mailboxes) {
60 mailboxes_for_frame[i++] =
61 gpu::MailboxHolder(mailbox, sync_token, texture_target);
64 base::BindOnce(&DestroySharedImages, std::move(context_provider),
65 std::move(mailboxes), std::move(destroyed_callback));
66 return VideoFrame::WrapNativeTextures(format, mailboxes_for_frame,
67 std::move(callback), coded_size,
68 visible_rect, natural_size, timestamp);
71 scoped_refptr<VideoFrame> CreateSharedImageRGBAFrame(
72 scoped_refptr<viz::ContextProvider> context_provider,
73 const gfx::Size& coded_size,
74 const gfx::Rect& visible_rect,
75 base::OnceClosure destroyed_callback) {
76 DCHECK_EQ(coded_size.width() % 4, 0);
77 DCHECK_EQ(coded_size.height() % 2, 0);
78 size_t pixels_size = coded_size.GetArea() * 4;
79 std::vector<uint8_t> pixels(pixels_size);
81 for (size_t block_y = 0; block_y < 2u; ++block_y) {
82 for (int y = 0; y < coded_size.height() / 2; ++y) {
83 for (size_t block_x = 0; block_x < 4u; ++block_x) {
84 for (int x = 0; x < coded_size.width() / 4; ++x) {
85 pixels[i++] = 0xffu * (block_x % 2); // R
86 pixels[i++] = 0xffu * (block_x / 2); // G
87 pixels[i++] = 0xffu * block_y; // B
88 pixels[i++] = 0xffu; // A
93 DCHECK_EQ(i, pixels_size);
95 auto* sii = context_provider->SharedImageInterface();
96 gpu::Mailbox mailbox =
97 sii->CreateSharedImage(viz::SinglePlaneFormat::kRGBA_8888, coded_size,
98 gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
99 kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
100 "RGBAVideoFrame", pixels)
103 return CreateSharedImageFrame(
104 std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_ABGR,
105 {mailbox}, {}, GL_TEXTURE_2D, coded_size, visible_rect,
106 visible_rect.size(), base::Seconds(1), std::move(destroyed_callback));
109 scoped_refptr<VideoFrame> CreateSharedImageI420Frame(
110 scoped_refptr<viz::ContextProvider> context_provider,
111 const gfx::Size& coded_size,
112 const gfx::Rect& visible_rect,
113 base::OnceClosure destroyed_callback) {
114 DCHECK_EQ(coded_size.width() % 8, 0);
115 DCHECK_EQ(coded_size.height() % 4, 0);
116 gfx::Size uv_size(coded_size.width() / 2, coded_size.height() / 2);
117 size_t y_pixels_size = coded_size.GetArea();
118 size_t uv_pixels_size = uv_size.GetArea();
119 std::vector<uint8_t> y_pixels(y_pixels_size);
120 std::vector<uint8_t> u_pixels(uv_pixels_size);
121 std::vector<uint8_t> v_pixels(uv_pixels_size);
124 for (size_t block_y = 0; block_y < 2u; ++block_y) {
125 for (int y = 0; y < coded_size.height() / 2; ++y) {
126 for (size_t block_x = 0; block_x < 4u; ++block_x) {
127 size_t color_index = block_x + block_y * 4;
128 const uint8_t* yuv = kYuvColors[color_index];
129 for (int x = 0; x < coded_size.width() / 4; ++x) {
130 y_pixels[y_i++] = yuv[0];
131 if ((x % 2) && (y % 2)) {
132 u_pixels[uv_i] = yuv[1];
133 v_pixels[uv_i++] = yuv[2];
139 DCHECK_EQ(y_i, y_pixels_size);
140 DCHECK_EQ(uv_i, uv_pixels_size);
142 auto plane_format = context_provider->ContextCapabilities().texture_rg
143 ? viz::SinglePlaneFormat::kR_8
144 : viz::SinglePlaneFormat::kLUMINANCE_8;
145 auto* sii = context_provider->SharedImageInterface();
146 gpu::Mailbox y_mailbox =
147 sii->CreateSharedImage(plane_format, coded_size, gfx::ColorSpace(),
148 kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
149 gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_Y",
152 gpu::Mailbox u_mailbox =
153 sii->CreateSharedImage(plane_format, uv_size, gfx::ColorSpace(),
154 kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
155 gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_U",
158 gpu::Mailbox v_mailbox =
159 sii->CreateSharedImage(plane_format, uv_size, gfx::ColorSpace(),
160 kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
161 gpu::SHARED_IMAGE_USAGE_GLES2, "I420Frame_V",
165 return CreateSharedImageFrame(
166 std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_I420,
167 {y_mailbox, u_mailbox, v_mailbox}, {}, GL_TEXTURE_2D, coded_size,
168 visible_rect, visible_rect.size(), base::Seconds(1),
169 std::move(destroyed_callback));
172 scoped_refptr<VideoFrame> CreateSharedImageNV12Frame(
173 scoped_refptr<viz::ContextProvider> context_provider,
174 const gfx::Size& coded_size,
175 const gfx::Rect& visible_rect,
176 base::OnceClosure destroyed_callback) {
177 DCHECK_EQ(coded_size.width() % 8, 0);
178 DCHECK_EQ(coded_size.height() % 4, 0);
179 if (!context_provider->ContextCapabilities().texture_rg) {
180 LOG(ERROR) << "GL_EXT_texture_rg not supported";
183 gfx::Size uv_size(coded_size.width() / 2, coded_size.height() / 2);
184 size_t y_pixels_size = coded_size.GetArea();
185 size_t uv_pixels_size = uv_size.GetArea() * 2;
186 std::vector<uint8_t> y_pixels(y_pixels_size);
187 std::vector<uint8_t> uv_pixels(uv_pixels_size);
190 for (size_t block_y = 0; block_y < 2u; ++block_y) {
191 for (int y = 0; y < coded_size.height() / 2; ++y) {
192 for (size_t block_x = 0; block_x < 4u; ++block_x) {
193 size_t color_index = block_x + block_y * 4;
194 const uint8_t* yuv = kYuvColors[color_index];
195 for (int x = 0; x < coded_size.width() / 4; ++x) {
196 y_pixels[y_i++] = yuv[0];
197 if ((x % 2) && (y % 2)) {
198 uv_pixels[uv_i++] = yuv[1];
199 uv_pixels[uv_i++] = yuv[2];
205 DCHECK_EQ(y_i, y_pixels_size);
206 DCHECK_EQ(uv_i, uv_pixels_size);
208 auto* sii = context_provider->SharedImageInterface();
209 gpu::Mailbox y_mailbox =
210 sii->CreateSharedImage(viz::SinglePlaneFormat::kR_8, coded_size,
211 gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
212 kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
213 "NV12Frame_Y", y_pixels)
215 gpu::Mailbox uv_mailbox =
216 sii->CreateSharedImage(viz::SinglePlaneFormat::kRG_88, uv_size,
217 gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
218 kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_GLES2,
219 "NV12Frame_UV", uv_pixels)
221 return CreateSharedImageFrame(
222 std::move(context_provider), VideoPixelFormat::PIXEL_FORMAT_NV12,
223 {y_mailbox, uv_mailbox}, {}, GL_TEXTURE_2D, coded_size, visible_rect,
224 visible_rect.size(), base::Seconds(1), std::move(destroyed_callback));