Flutter Engine
The Flutter Engine
SkYUVAInfo.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
11#include "src/base/SkSafeMath.h"
13
14#include <algorithm>
15
17 SkYUVAInfo::Subsampling subsampling) {
19 subsampling == SkYUVAInfo::Subsampling::kUnknown) {
20 return false;
21 }
22 return subsampling == SkYUVAInfo::Subsampling::k444 ||
27}
28
29std::tuple<int, int> SkYUVAInfo::SubsamplingFactors(Subsampling subsampling) {
30 switch (subsampling) {
31 case Subsampling::kUnknown: return {0, 0};
32 case Subsampling::k444: return {1, 1};
33 case Subsampling::k422: return {2, 1};
34 case Subsampling::k420: return {2, 2};
35 case Subsampling::k440: return {1, 2};
36 case Subsampling::k411: return {4, 1};
37 case Subsampling::k410: return {4, 2};
38 }
40}
41
42std::tuple<int, int> SkYUVAInfo::PlaneSubsamplingFactors(PlaneConfig planeConfig,
43 Subsampling subsampling,
44 int planeIdx) {
46 planeIdx < 0 ||
47 planeIdx > NumPlanes(planeConfig)) {
48 return {0, 0};
49 }
50 bool isSubsampledPlane = false;
51 switch (planeConfig) {
53
58 isSubsampledPlane = planeIdx == 1 || planeIdx == 2;
59 break;
60
65 isSubsampledPlane = planeIdx == 1;
66 break;
67
72 break;
73 }
74 return isSubsampledPlane ? SubsamplingFactors(subsampling) : std::make_tuple(1, 1);
75}
76
78 PlaneConfig planeConfig,
79 Subsampling subsampling,
80 SkEncodedOrigin origin,
81 SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]) {
84 return 0;
85 }
86
87 int w = imageDimensions.width();
88 int h = imageDimensions.height();
90 using std::swap;
91 swap(w, h);
92 }
93 auto down2 = [](int x) { return (x + 1)/2; };
94 auto down4 = [](int x) { return (x + 3)/4; };
95 SkISize uvSize;
96 switch (subsampling) {
98
99 case Subsampling::k444: uvSize = { w , h }; break;
100 case Subsampling::k422: uvSize = {down2(w), h }; break;
101 case Subsampling::k420: uvSize = {down2(w), down2(h)}; break;
102 case Subsampling::k440: uvSize = { w , down2(h)}; break;
103 case Subsampling::k411: uvSize = {down4(w), h }; break;
104 case Subsampling::k410: uvSize = {down4(w), down2(h)}; break;
105 }
106 switch (planeConfig) {
108
111 planeDimensions[0] = {w, h};
112 planeDimensions[1] = planeDimensions[2] = uvSize;
113 return 3;
114
117 planeDimensions[0] = {w, h};
118 planeDimensions[1] = uvSize;
119 return 2;
120
123 planeDimensions[0] = planeDimensions[3] = {w, h};
124 planeDimensions[1] = planeDimensions[2] = uvSize;
125 return 4;
126
129 planeDimensions[0] = planeDimensions[2] = {w, h};
130 planeDimensions[1] = uvSize;
131 return 3;
132
137 planeDimensions[0] = {w, h};
138 SkASSERT(planeDimensions[0] == uvSize);
139 return 1;
140 }
142}
143
144static bool channel_index_to_channel(uint32_t channelFlags,
145 int channelIdx,
146 SkColorChannel* channel) {
147 switch (channelFlags) {
148 case kGray_SkColorChannelFlag: // For gray returning any of R, G, or B for index 0 is ok.
150 if (channelIdx == 0) {
151 *channel = SkColorChannel::kR;
152 return true;
153 }
154 return false;
156 switch (channelIdx) {
157 case 0: *channel = SkColorChannel::kR; return true;
158 case 1: *channel = SkColorChannel::kA; return true;
159
160 default: return false;
161 }
163 if (channelIdx == 0) {
164 *channel = SkColorChannel::kA;
165 return true;
166 }
167 return false;
169 if (channelIdx == 0 || channelIdx == 1) {
170 *channel = static_cast<SkColorChannel>(channelIdx);
171 return true;
172 }
173 return false;
175 if (channelIdx >= 0 && channelIdx <= 2) {
176 *channel = static_cast<SkColorChannel>(channelIdx);
177 return true;
178 }
179 return false;
181 if (channelIdx >= 0 && channelIdx <= 3) {
182 *channel = static_cast<SkColorChannel>(channelIdx);
183 return true;
184 }
185 return false;
186 default:
187 return false;
188 }
189}
190
192 const uint32_t* planeChannelFlags) {
193 // Like YUVALocation but chanIdx refers to channels by index rather than absolute channel, e.g.
194 // A is the 0th channel of an alpha-only texture. We'll use this plus planeChannelFlags to get
195 // the actual channel.
196 struct PlaneAndIndex {int plane, chanIdx;};
197 const PlaneAndIndex* planesAndIndices = nullptr;
198 switch (config) {
200 return {};
201
202 case PlaneConfig::kY_U_V: {
203 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 0}, {2, 0}, {-1, -1}};
204 planesAndIndices = kPlanesAndIndices;
205 break;
206 }
207 case PlaneConfig::kY_V_U: {
208 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {2, 0}, {1, 0}, {-1, -1}};
209 planesAndIndices = kPlanesAndIndices;
210 break;
211 }
212 case PlaneConfig::kY_UV: {
213 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 0}, {1, 1}, {-1, -1}};
214 planesAndIndices = kPlanesAndIndices;
215 break;
216 }
217 case PlaneConfig::kY_VU: {
218 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 1}, {1, 0}, {-1, -1}};
219 planesAndIndices = kPlanesAndIndices;
220 break;
221 }
222 case PlaneConfig::kYUV: {
223 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {0, 1}, {0, 2}, {-1, -1}};
224 planesAndIndices = kPlanesAndIndices;
225 break;
226 }
227 case PlaneConfig::kUYV: {
228 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 1}, {0, 0}, {0, 2}, {-1, -1}};
229 planesAndIndices = kPlanesAndIndices;
230 break;
231 }
233 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
234 planesAndIndices = kPlanesAndIndices;
235 break;
236 }
238 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {2, 0}, {1, 0}, {3, 0}};
239 planesAndIndices = kPlanesAndIndices;
240 break;
241 }
243 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}};
244 planesAndIndices = kPlanesAndIndices;
245 break;
246 }
248 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {1, 1}, {1, 0}, {2, 0}};
249 planesAndIndices = kPlanesAndIndices;
250 break;
251 }
252 case PlaneConfig::kYUVA: {
253 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 0}, {0, 1}, {0, 2}, {0, 3}};
254 planesAndIndices = kPlanesAndIndices;
255 break;
256 }
257 case PlaneConfig::kUYVA: {
258 static constexpr PlaneAndIndex kPlanesAndIndices[] = {{0, 1}, {0, 0}, {0, 2}, {0, 3}};
259 planesAndIndices = kPlanesAndIndices;
260 break;
261 }
262 }
263 SkASSERT(planesAndIndices);
264 YUVALocations yuvaLocations;
265 for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
266 auto [plane, chanIdx] = planesAndIndices[i];
267 SkColorChannel channel;
268 if (plane >= 0) {
269 if (!channel_index_to_channel(planeChannelFlags[plane], chanIdx, &channel)) {
270 return {};
271 }
272 yuvaLocations[i] = {plane, channel};
273 } else {
274 SkASSERT(i == 3);
275 yuvaLocations[i] = {-1, SkColorChannel::kR};
276 }
277 }
278 return yuvaLocations;
279}
280
282 switch (planeConfig) {
283 case PlaneConfig::kUnknown: return false;
284
285 case PlaneConfig::kY_U_V: return false;
286 case PlaneConfig::kY_V_U: return false;
287 case PlaneConfig::kY_UV: return false;
288 case PlaneConfig::kY_VU: return false;
289 case PlaneConfig::kYUV: return false;
290 case PlaneConfig::kUYV: return false;
291
292 case PlaneConfig::kY_U_V_A: return true;
293 case PlaneConfig::kY_V_U_A: return true;
294 case PlaneConfig::kY_UV_A: return true;
295 case PlaneConfig::kY_VU_A: return true;
296 case PlaneConfig::kYUVA: return true;
297 case PlaneConfig::kUYVA: return true;
298 }
300}
301
303 PlaneConfig planeConfig,
304 Subsampling subsampling,
305 SkYUVColorSpace yuvColorSpace,
306 SkEncodedOrigin origin,
307 Siting sitingX,
308 Siting sitingY)
309 : fDimensions(dimensions)
310 , fPlaneConfig(planeConfig)
311 , fSubsampling(subsampling)
312 , fYUVColorSpace(yuvColorSpace)
313 , fOrigin(origin)
314 , fSitingX(sitingX)
315 , fSitingY(sitingY) {
316 if (fDimensions.isEmpty() ||
318 *this = {};
319 SkASSERT(!this->isValid());
320 return;
321 }
322 SkASSERT(this->isValid());
323}
324
325size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
326 size_t planeSizes[kMaxPlanes]) const {
327 if (!this->isValid()) {
328 return 0;
329 }
330 SkSafeMath safe;
331 size_t totalBytes = 0;
333 int n = this->planeDimensions(planeDimensions);
334 for (int i = 0; i < n; ++i) {
335 SkASSERT(!planeDimensions[i].isEmpty());
336 SkASSERT(rowBytes[i]);
337 size_t size = safe.mul(rowBytes[i], planeDimensions[i].height());
338 if (planeSizes) {
339 planeSizes[i] = size;
340 }
341 totalBytes = safe.add(totalBytes, size);
342 }
343 if (planeSizes) {
344 if (safe.ok()) {
345 for (int i = n; i < kMaxPlanes; ++i) {
346 planeSizes[i] = 0;
347 }
348 } else {
349 for (int i = 0; n < kMaxPlanes; ++i) {
350 planeSizes[i] = SIZE_MAX;
351 }
352 }
353 }
354
355 return safe.ok() ? totalBytes : SIZE_MAX;
356}
357
358SkYUVAInfo::YUVALocations SkYUVAInfo::toYUVALocations(const uint32_t* channelFlags) const {
359 return GetYUVALocations(fPlaneConfig, channelFlags);
360}
361
363 return {fDimensions, fPlaneConfig, subsampling, fYUVColorSpace, fOrigin, fSitingX, fSitingY};
364}
365
367 return {dimensions, fPlaneConfig, fSubsampling, fYUVColorSpace, fOrigin, fSitingX, fSitingY};
368}
369
370bool SkYUVAInfo::operator==(const SkYUVAInfo& that) const {
371 return fPlaneConfig == that.fPlaneConfig &&
372 fSubsampling == that.fSubsampling &&
373 fYUVColorSpace == that.fYUVColorSpace &&
374 fDimensions == that.fDimensions &&
375 fSitingX == that.fSitingX &&
376 fSitingY == that.fSitingY &&
377 fOrigin == that.fOrigin;
378}
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorChannel
Definition: SkColor.h:228
@ kRGB_SkColorChannelFlags
Definition: SkColor.h:247
@ kRGBA_SkColorChannelFlags
Definition: SkColor.h:248
@ kRed_SkColorChannelFlag
Definition: SkColor.h:239
@ kGrayAlpha_SkColorChannelFlags
Definition: SkColor.h:245
@ kRG_SkColorChannelFlags
Definition: SkColor.h:246
@ kAlpha_SkColorChannelFlag
Definition: SkColor.h:242
@ kGray_SkColorChannelFlag
Definition: SkColor.h:243
SkEncodedOrigin
@ kLeftTop_SkEncodedOrigin
SkYUVColorSpace
Definition: SkImageInfo.h:68
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static bool channel_index_to_channel(uint32_t channelFlags, int channelIdx, SkColorChannel *channel)
Definition: SkYUVAInfo.cpp:144
static bool is_plane_config_compatible_with_subsampling(SkYUVAInfo::PlaneConfig config, SkYUVAInfo::Subsampling subsampling)
Definition: SkYUVAInfo.cpp:16
size_t add(size_t x, size_t y)
Definition: SkSafeMath.h:33
bool ok() const
Definition: SkSafeMath.h:26
size_t mul(size_t x, size_t y)
Definition: SkSafeMath.h:29
SkYUVAInfo()=default
@ kY_U_V_A
Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A.
@ kY_U_V
Plane 0: Y, Plane 1: U, Plane 2: V.
@ kYUVA
Plane 0: YUVA.
@ kY_V_U_A
Plane 0: Y, Plane 1: V, Plane 2: U, Plane 3: A.
@ kUYVA
Plane 0: UYVA.
@ kY_VU
Plane 0: Y, Plane 1: VU.
@ kY_UV
Plane 0: Y, Plane 1: UV.
@ kY_VU_A
Plane 0: Y, Plane 1: VU, Plane 2: A.
@ kY_V_U
Plane 0: Y, Plane 1: V, Plane 2: U.
@ kY_UV_A
Plane 0: Y, Plane 1: UV, Plane 2: A.
static constexpr int kMaxPlanes
Definition: SkYUVAInfo.h:98
@ k440
1 set of UV values for each 1x2 block of Y values.
@ k420
1 set of UV values for each 2x2 block of Y values.
@ k410
1 set of UV values for each 4x2 block of Y values.
@ k411
1 set of UV values for each 4x1 block of Y values.
@ k422
1 set of UV values for each 2x1 block of Y values.
@ k444
No subsampling. UV values for each Y.
static YUVALocations GetYUVALocations(PlaneConfig, const uint32_t *planeChannelFlags)
Definition: SkYUVAInfo.cpp:191
size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes], size_t planeSizes[kMaxPlanes]=nullptr) const
Definition: SkYUVAInfo.cpp:325
SkYUVAInfo makeDimensions(SkISize) const
Definition: SkYUVAInfo.cpp:366
YUVALocations toYUVALocations(const uint32_t *channelFlags) const
Definition: SkYUVAInfo.cpp:358
int height() const
Definition: SkYUVAInfo.h:173
static constexpr int NumPlanes(PlaneConfig)
Definition: SkYUVAInfo.h:253
SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const
Definition: SkYUVAInfo.cpp:362
PlaneConfig planeConfig() const
Definition: SkYUVAInfo.h:160
int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const
Definition: SkYUVAInfo.h:192
static std::tuple< int, int > SubsamplingFactors(Subsampling)
Definition: SkYUVAInfo.cpp:29
std::array< YUVALocation, kYUVAChannelCount > YUVALocations
Definition: SkYUVAInfo.h:32
static int PlaneDimensions(SkISize imageDimensions, PlaneConfig, Subsampling, SkEncodedOrigin, SkISize planeDimensions[kMaxPlanes])
Definition: SkYUVAInfo.cpp:77
SkEncodedOrigin origin() const
Definition: SkYUVAInfo.h:179
static constexpr int kYUVAChannelCount
Definition: SkYUVAInfo.h:29
bool isValid() const
Definition: SkYUVAInfo.h:233
static bool HasAlpha(PlaneConfig)
Definition: SkYUVAInfo.cpp:281
static std::tuple< int, int > PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx)
Definition: SkYUVAInfo.cpp:42
Subsampling subsampling() const
Definition: SkYUVAInfo.h:161
SkISize dimensions() const
Definition: SkYUVAInfo.h:171
bool operator==(const SkYUVAInfo &that) const
Definition: SkYUVAInfo.cpp:370
double x
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SkScalar w
SkScalar h
Definition: SkSize.h:16
bool isEmpty() const
Definition: SkSize.h:31
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37