Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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)
static bool is_plane_config_compatible_with_subsampling(SkYUVAInfo::PlaneConfig config, SkYUVAInfo::Subsampling subsampling)
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)
size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes], size_t planeSizes[kMaxPlanes]=nullptr) const
SkYUVAInfo makeDimensions(SkISize) const
YUVALocations toYUVALocations(const uint32_t *channelFlags) const
int height() const
Definition SkYUVAInfo.h:173
static constexpr int NumPlanes(PlaneConfig)
Definition SkYUVAInfo.h:253
SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const
PlaneConfig planeConfig() const
Definition SkYUVAInfo.h:160
int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const
Definition SkYUVAInfo.h:192
static std::tuple< int, int > SubsamplingFactors(Subsampling)
std::array< YUVALocation, kYUVAChannelCount > YUVALocations
Definition SkYUVAInfo.h:32
static int PlaneDimensions(SkISize imageDimensions, PlaneConfig, Subsampling, SkEncodedOrigin, SkISize planeDimensions[kMaxPlanes])
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)
static std::tuple< int, int > PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx)
Subsampling subsampling() const
Definition SkYUVAInfo.h:161
SkISize dimensions() const
Definition SkYUVAInfo.h:171
bool operator==(const SkYUVAInfo &that) const
double x
SkScalar w
SkScalar h
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